1

テキストと環境変数への参照を含むファイルがあります。例:

#PRINTME It is always fun to start your week on a sunny ${DAY_OF_WEEK}
#PRINTME My name is ${USERNAME}, you killed my father - prepare to die!
Unrelated gibberish - not to be printed
...

メタデータと考えてください。

#PRINTMEこのファイルを取得し、でマークされたすべてのものを出力し、環境変数も評価するコマンドを定義したいと思います。

私はこれをしました:grep #HELP myfile | sed "s/#PRINTME //g" | awk '{print $1}'しかし私の出力は

It is always fun to start your week on a sunny ${DAY_OF_WEEK}
My name is ${USERNAME}, you killed my father - prepare to die!

それ以外の

It is always fun to start your week on a sunny Monday
My name is Inigo Montoya, you killed my father - prepare to die!

私がやりたいことをするシェルの方法はありますか?私は使用してTCSHいます-それを変更することはできません。grep、、の置き換えに問題はsedありませんawk

4

4 に答える 4

3

Perlを使用しますが、Python、Ruby、Tcl / Tk、...などの任意のスクリプト言語でコーディングできます。

それはちょうど約1つのライナーです:

perl -n -e 'next unless m/^#PRINTME /;s/#PRINTME //;s/\$\{(\w+\)\}/$ENV{$1}/eg;print;'

は行-nを読み取ることを意味しますが、それらを自動的に印刷しません(think sed -n)。next印刷されない行をスキップします。最初の代替は、印刷マーカーを削除します。花火は2番目の代替品です:

  • を探してから${WORD}、それを式として評価するオプションを$ENV{WORD}使用して(おそらく、現時点では正規表現ではないため、不規則です。これは単なる正規表現です)、グローバルに行います。eg

次に、残っているものを印刷します。

(コードは現在テスト済みです。)

$ cat xx.sh
DAY_OF_WEEK=Tuesday USERNAME="Inigo Montoya" \
perl -n -e 'next unless m/^#PRINTME /; s/#PRINTME //; s/\$\{(\w+)\}/$ENV{$1}/eg; print;' <<EOF

#PRINTME It is always fun to start your week on a sunny ${DAY_OF_WEEK}
#PRINTME My name is ${USERNAME}, you killed my father - prepare to die!
Unrelated gibberish - not to be printed
...

EOF
$ sh xx.sh
It is always fun to start your week on a sunny Tuesday
My name is Inigo Montoya, you killed my father - prepare to die!
$
于 2012-07-17T21:14:07.743 に答える
2

ENVIRONで配列を使用できますawk。たとえば、これを試してください。

awk 'BEGIN {print ENVIRON["HOME"]}' </dev/null
于 2012-07-17T21:10:57.917 に答える
2

あなたはGawkでそれを行うことができます:

gawk '

  /^#PRINTME/ {

    # Remove prefix
    sub( /^#PRINTME /, "" )

    # Loop while the line contains variables
    while( /\$\{[^}]+\}/ ) {

      # Extract the first variable name
      VAR = gensub( /^[^$]*\$\{([^}]+)\}.*$/, "\\1", 1 )

      # Replace it with its value
      gsub( "\\$\\{" VAR "\\}", ENVIRON[ VAR ] )
    }

    print

 }
'

スクリプトは変数を1つずつ見つけて、それらの値に置き換えます。

OSに変数を評価させたい場合は、さらに簡単です(そして標準のAwkで実行可能です)。

awk '/^#PRINTME/ { sub( /^#PRINTME /, "" ) ; system( "echo " $0 ) }'

今回は、echoコマンドを作成し、シェルに渡します。

于 2012-07-17T21:57:14.653 に答える
1

次のような式を処理します${foo:-bar}か?コメントに、コマンドが含まれている場合にその行を評価したいという記述があるので、おそらく単にを使用したいと思いますeval。入力が制御されていない場合は、セキュリティ上の大きなリスクが伴うことに注意してください。でsh、次のことができます。

sh$ < myfile sed -e '/#HELP/!d' -e 's/#PRINTME //g' |
 while read line; do eval echo "\"$line\""; done 

本当にtcshを使用せざるを得ない場合は、次のことを試してください。

tcsh$ sh -c '< myfile sed -e "/#HELP/!d" -e "s/#PRINTME //g" |\
            while read line; do eval echo "\"$line\""; done'

(あなたのコードは#HELP行を除外しますが、あなたはそれについて言及していません。あなたが投稿した出力は、あなたawk '{print $1}'が本当にそうであったことを示唆していますawk '{print $0}'。私はそれらすべてを単一のsed呼び出しに結合しましたsed -n '/#HELP/s/#PRINTME //gp'。確かに^)でパターンを固定することを検討してください

于 2012-07-18T11:24:19.340 に答える