スラッシュを含めることができるファイルに最初に表示されるパターンを置き換えます。

スラッシュを含めることができるファイルに最初に表示されるパターンを置き換えます。

ありがとうこのリンク私はどうするか知っていますスラッシュを含む変数を渡すsedパターンで:

sed "s~$var~replace~g" $file。 / 代わりにシングルバイト文字を使用してください。

ありがとうこの他のリンク私も知る方法ファイルに最初に表示されるパターンのみを置き換える(同じ行にはありません):

sed "0,/$var/s/$var/replacement/" filename または sed 0,/$var/{s/$var/replacement/} filename

しかし、それを行うと( sed '0,~$var~s~$var~replacement~' filename またはゼロで始まり、スラッシュがない他のもの)エラーが発生します。unknown command: '0'

この2つをどのように組み合わせることができますか?おそらくawkやPerlを使うか…?

答え1

しかし:

sed "0,\~$var~s~$var~replacement~"

正規表現の区切り文字を変更するために使用できます。sed通常、コード(または他のインタプリタ)コードに変数拡張を含めることは非常に賢明ではありません。

まず、この区切り文字はエスケープする必要がある唯一の文字ではありません。これはすべての正規表現演算子にも必要です。

しかし、より重要なことは、特にGNUの場合、sedこれはコマンドインジェクションの脆弱性です。コンテンツを$var制御できない場合は、任意のデータをeval

たとえば、次のようになります。

$ var='^~s/.*/uname/e;#'
$ echo | sed "0,\~$var~s~$var~replacement~"
Linux

コマンドunameが実行され、幸い今回は無害でした。

GNU以外sedの実装では任意のコマンドを実行することはできませんが、コマンドを使用してすべてのファイルを上書きすることができます。wこれは実際には同じです。

より正確な方法は$varまず、問題のある文字を脱出してください:

NL='
'
case $var in
  (*"$NL"*)
    echo >&2 "Sorry, can't handle variables with newline characters"
    exit 1
esac
escaped_var=$(printf '%s\n' "$var" | sed 's:[][\/.^$*]:\\&:g')
# and then:
sed "0,/$escaped_var/s/$escaped_var/replacement/" < file

別の方法は、次のものを使用することですperl

var=$var perl -pe 's/\Q$ENV{var}\E/replacement/g && $n++ unless $n' < file

$var渡されたコード内の内容を拡張せずにperl(別のコマンドインジェクションの脆弱性になる可能性があります)、代わりにperlその内容を正規表現処理の一部に拡張します(\Q...\Eつまり、正規表現演算子が特に処理されないことを意味します)。

改行文字が含まれている場合は、$var最後に 1 つだけで一致が可能です。あるいは、-0777入力が1行ずつ処理されず、単一のレコードとして処理されるようにこのオプションを渡すこともできます。

答え2

Stephaneのソリューションと同様に、perlawk危険な」補間を保護する問題は、代替手段によって回避できます。

export pattern="anypattern" # or whatever shell quoting is needed
awk 'NR==1,$0~ENVIRON["pattern"] {sub(ENVIRON["pattern"],"replacement")} 1' input
# or gsub if you want multiple matches on the first line with any match

データが(おそらく)大きく、パターンが(おそらく)高価な場合は、わずかにawk異なるイディオムと一致するものを見つけると、不要な一致を避けることができます。

awk '!x&&$0~ENVIRON["pattern"] {sub(ENVIRON["pattern"],"replacement");x=1} 1' input
# ditto

注意:(awkまたはsed)実際のプレフィックスが&必要な場合(通常は最初にシェルから引用する必要があり、ここではにある)、同様に実際のプレフィックスを2倍にします。&\''\

関連情報