特定の行の別の変数テキストの後に変数テキストを挿入する

特定の行の別の変数テキストの後に変数テキストを挿入する

特定の行で、別の変数テキストの後に変数テキストを挿入しようとしています。以下は、これまでの私の試みです。私が知る限り、引用符をエスケープしてawk変数が表示され、適用され続けるようにできれば、うまくいくはずですが、その方法がわかりません。

#!/bin/sh

VAR=$(head -n1 ~/Scripts/tmp/file.txt)
VAR1=$(head -n1 ~/Scripts/tmp/file1.txt)

awk '/$VAR/ { print; print "$VAR1"; next }1' ~/Scripts/tmp/file.txt

答え1

文字列を awk スクリプトに渡すには、環境変数を介して渡します。

export VAR VAR1
awk '
    1
    $0 == ENVIRON["VAR"] {print ENVIRON["VAR1"]}
' ~/Scripts/tmp/file.txt

ロジックをシンプルにするためにスクリプトを再編成しました。また、正規表現のマッチングを文字列の比較に置き換えました。正規表現のマッチングでは、$VAR正規表現として扱われ、文字列の比較は実行されません。また、そのために必要となる の値 (これは Perl 構文であり、awk ではありません)/$VAR/も使用されません。VARmatch($0, VAR)

実際には機能しない他の解決策についての注意 (変数に特殊文字が含まれていない場合にのみ機能します。どの文字が特殊であるかは方法によって異なります)。

  • awk -v awkvar="$VAR" '$0 == awkvar …'行の内容内のバックスラッシュを展開します。
  • awk "/$VAR/" …シェルは の値をVARawk スニペットとして展開します。たとえば、file.txtが含まれている場合^/ {system("touch ~/naughty")} /、コマンドがtouch ~/naughty実行されます。

別の方法としては、awk にすべてのファイルを読み取らせることです。

awk '
    BEGIN { VAR1 = getline <"~/Scripts/tmp/file1.txt"; }
    NR == 1 {VAR = $0}
    1
    $0 == ENVIRON["VAR"] {print ENVIRON["VAR1"]}
' ~/Scripts/tmp/file.txt

答え2

考えられる AWK の解決策の 1 つ:

   awk '/'$VAR'/ { print; print "'$VAR1'"; next }1'

すべての外部変数を囲む ' 引用符を分割します。

他の投稿で提案されているように、変数を渡す別の解決策としては、VAR1 を awk 変数として渡すことが考えられますが、VAR を使用するパターンでは、依然として一重引用符ブロック エスケープを実行する必要があると思います。

 awk -v var=$VAR1 '/'$VAR'/ { print; print var; next }1'

代わりに sed を試すこともできます :) この種の置換用に特別に設計されています。

 sed "s/$VAR.*/\0\n$VAR1/" ~/Scripts/tmp/file.txt     

1 行に複数の VAR インスタンスを記述できる場合は、sed コマンド (グローバル) の最後に g を追加して、最初に見つかった一致で停止しないようにします。

 sed "s/$VAR.*/\0 $VAR1/g" ~/Scripts/tmp/file.txt 

重要: VAR または VAR1 変数に '/' 文字が含まれていないことを確認してください。含まれている場合は、awk または sed でエスケープする必要があります。または、sed でコマンドの区切り文字を ';' などの別の文字に変更できます。例:

 sed "s;$VAR.*;\0\n$VAR1;" ~/Scripts/tmp/file.txt

sed コマンドの説明:
sed コマンドの前後に一重引用符ではなく二重引用符を使用して、VAR や VAR1 などの変数がその値に置き換えられるようにします。これは、sed によってコマンドが実行される前に行われるため、変数の内容に / が存在する可能性がある場合は、それを処理する必要があります (awk の場合も同様です)。
's' は、次の形式の置換コマンドを記述していることを示します:
s/<パターン>/<置換パターン>/
s の直後の '/' は、コマンドのセクションを区切るために使用される区切り文字です。したがって、; を配置する場合は、上記のようにすべての場所で ; を使用する必要があります。一致するパターンは、$VAR 変数の内容になります。置換パターンは \0 で、パターンに一致したもの、新しい行 '\n'、および VAR2 の内容を出力することを意味します。

OOPS は、以下の行の部分を見逃しました。固定パターンです。

答え3

を使用する場合は、オプションを使用して変数を にawk渡す必要があります。 bashawk-v

awk -v v=$VAR -v v1=$VAR1 '/v/ { print; print v1; next }1' ~/Scripts/tmp/file.txt

ただし、より正確で詳細な解決策については、Rob の回答を確認してください。

関連情報