変数と引用符を使用するようにsedを取得できません

変数と引用符を使用するようにsedを取得できません

この行を置き換えるシェルスクリプトを作成します。

exec "$progdir/$program" ${1+"$@"}

そして:

exec qemu-arm -L /mnt/c/git/build/linux_arm7/build_arm7/sysroot "$progdir/$program" ${1+"$@"}

ファイルから。 /mnt/c/git/build/linux_arm7/build_arm7という名前の変数にありますBUILD_DIRECTORY。私が何をしようとしても(引用符、他の区切り文字)、常に置換の代わりに変数で終わります。たとえば、私はこれを試しました:

#!/bin/bash
sed_test()
{
    sed -i 's|exec "\$progdir\/\$program" \${1+"\$@"}|exec qemu-arm -L ${BUILD_DIRECTORY}\/sysroot "\$progdir\/\$program" \${1+"\$@"}|g' ${BUILD_DIRECTORY}/file
}

ファイルにこれを得ました:

exec qemu-arm -L ${BUILD_DIRECTORY}/sysroot "$progdir/$program" ${1+"$@"}

これを正しく行う方法は?

答え1

  • ${BUILD_DIRECTORY}参照により変数の拡張が防止される
  • g最終不要
  • あなたはとても逃げました。

BUILD_DIRECTORY 変数にスペースがない場合は、次のようにします。

sed -i 's|exec "$progdir/$program" ${1+"$@"}|exec qemu-arm -L '${BUILD_DIRECTORY}'/sysroot "$progdir/$program" ${1+"$@"}|'  ${BUILD_DIRECTORY}/file

周囲の一重引用符に注意してください。${BUILD_DIRECTORY}

BUILD_DIRECTORYにスペースがある場合(たとえばlinux arm7)、リレー文字列を使用します(コマンド分割)。

sed -e 's|exec "$progdir/$program" ${1+"$@"}|exec qemu-arm -L BUILD_DIRECTORY/sysroot "$progdir/$program" ${1+"$@"}|'  
   -e "s|BUILD_DIRECTORY|${BUILD_DIRECTORY}|" 
   "${BUILD_DIRECTORY}/file"

生産する

exec qemu-arm -L /mnt/c/git/build/linux arm7/build_arm7/sysroot "$progdir/$program" ${1+"$@"}

答え2

そして:zshperl

SRC='exec "$progdir/$program" ${1+"$@"}' \
  DST='exec qemu-arm -L '${(qq)BUILD_DIRECTORY}' "$progdir/$program" ${1+"$@"}' \
  perl -pi -e 's/\Q$ENV{SRC}\E/$ENV{DST}/g' -- "$BUILD_DIRECTORY/file"

Bourneなどのシェルコードを編集しているので、結果が有効なシェルコードであることを確認する必要があります。したがって、、、スペースなどのシェル構文の特殊文字が含まれていても、結果を解析するときにその値が引数として渡されるよう$BUILD_DIRECTORYに変数の内容を挿入する必要があります。 。shqemu-arm;?'

最善の方法は、最も安全な引用モードである一重引用符で表現することです。sh変数に一重引用符文字が含まれている場合は、\'一重引用符の外側に挿入してください。これがqqパラメータ拡張フラグの役割ですzsh。たとえば、次のようになります。

  • 空の文字列を入れます。''
  • a;b入力する'a;b'
  • a'b入力する'a'\''b'

$BUID_DIRECTORY渡されたコード内の値を拡張すると、そのコンテキストで特殊文字をエスケープしない限り、コード注入の脆弱性が発生することを意味しますsedsedまた、-ised参照からコピーしたいくつかの実装perl)は標準ではありません。

代わりに使用することは、perl次のことを意味します。

  • -iポータブルで使用できます
  • /を$SRC使用してエスケープできるため、正規表現演算子をエスケープする必要はありません。\Q\E
  • 代替を避ける必要はありません。

答え3

sedコードを挿入するために変数を使用する方法は、s///コマンドのLHSまたはRHSで使用されているかどうかに応じて、最初にシェル検証可能なコンテンツをエスケープすることです。

& \ and :あなたのシナリオでは、ビルド変数がrhsに配置されます。したがって、実際のsedコードは区切り文字として使用されるため、文字をエスケープする必要がありますs:::。また、ビルド変数が複数行の場合、改行もエスケープされます。変数は一重引用符で囲まれているため、'\''ビルド変数に一重引用符がある場合は、すべての一重引用符も変更する必要があります。

BUILD_DIRECTORY='/mnt/c/git/build/linux_arm7/build_arm7'

BUILD_DIRECTORY_rhs=$(printf '%s\n' "${BUILD_DIRECTORY}" |
sed \
  -e 's/[\&:]/\\&/g'    \
  -e 's/'\''/&\\\\&&/g' \
  -e '$!s/$/\\/')

sed -i -e 's:^exec \("$progdir/$program" ${1+"$@"}\)$:'"exec qemu-arm -L '${BUILD_DIRECTORY_rhs}/sysroot' \\1:"  -- "${BUILD_DIRECTORY}/file"

この出力は次のようになります。

exec qemu-arm -L '/mnt/c/git/build/linux_arm7/build_arm7/sysroot' "$progdir/$program" ${1+"$@"}

関連情報