環境変数はコマンドライン引数内では拡張されません。

環境変数はコマンドライン引数内では拡張されません。

user-pid.out2「ユーザーID」と「プロセスID」の2つの列で構成されるファイルがあります。ユーザー番号に基づいて対応するプロセスIDを見つけたいと思います。下の最初の2行は正しい出力を示していませんが、3行と4行でユーザーを62にハードコードすると、ユーザー62に対応するプロセスIDが表示されます。誰でも助けることができますか?

USR=62
usrpid=`awk '$1 == "$USR" {print $2}' /home/hu/batchhu/dbscripts_tst2/user-pid.out2`
echo "first:" $USR $usrpid
# This shows 62 and blank for process id

usrpid=`awk '$1 == "62" {print $2}' /home/hu/batchhu/dbscripts_tst2/user-pid.out2`
echo  "second:" $USR $usrpid
# This shows 62 and process id corresponding to this user in the file user-pid.out2

答え1

@artmは、awkスクリプトを二重引用符で囲み、さまざまな文字をエスケープする技術を実演しました。ここに3つの技術があります。

シェルが変数を拡張できるように、単一引用符を区切ります。

usrpid=$(awk '$1 == "'"$USR"'" {print $2}' file)

シェル変数をawk変数に渡す

usrpid=$(awk -v usr="$USR" '$1 == usr {print $2}' file)

変数をエクスポートする場合は、awkのENVIRON配列を使用してください。

usrpid=$(awk '$1 == ENVIRON["USR"] {print $2}' file)

後者を好む必要があります。

@artmのアプローチなどの最初のアプローチでは、シェル変数の内容がコードに含まれていますawkコマンド注入の脆弱性変数の内容が厳密に制御されていない場合(たとえばを使用して)USR='blah" || system("reboot") || "'呼び出されますreboot

2番目はコマンドインジェクションの脆弱性を引き起こしませんが、バックスラッシュ文字が含まれている場合、Cと同様のバックスラッシュエスケープシーケンスが拡張されるため、変数に$USRシェル変数と同じ内容は含まれません。usr awk$USRawk

使用時にENVIRONそのような問題はありません。

答え2

最初の例は、"$USR"一重引用符で囲まれた文字列内に表示されるため、拡張されません'$1 == "$USR" { print $2 }'。したがって、このコードは、最初の列が62ではなく「$ USR」の行を探します。

次は動作します。

usrpid=$(awk "\$1 == \"$USR\" {print \$2}" /home/hu/batchhu/dbscripts_tst2/user-pid.out2)

多様性:

  1. awkコマンドラインは二重引用符を使用するため、$ USRが拡張されます。
  2. awkプログラムでは、ドル記号と引用符文字がエスケープされます。
  3. $()バックティックの代わりに使用してください。バックスラッシュが正しく処理されます。

の値はUSRawkスクリプトに直接挿入されるため、awkが文字通り解釈する文字のみが値に含まれている場合にのみ機能します。またはが$USR含まれている場合はすべてが分解されます。これはawk文字列リテラルの終わりになります。次の文字を引用します。\""\

関連情報