sedは毎回単語の境界のみを一致します。

sedは毎回単語の境界のみを一致します。

コマンドファイルに代替リストを保持したいと思います。

subs.sed

s/hello/foo/g
s/world/bar/g

私はこのように動作します。sed -i -f subs.sed file.txt

file.txtからhello worldfoo bar

しかし、私はこのようなことが起こらないようにしたいと思います。もしfile.txtそうhelloworldなら、上記の2つの代替のいずれも起こりたくありません。現在の出力はfoobarだが出力はhelloworld

コマンドファイルで単語の境界を手動で指定できます。

s/\<hello\>/foo/g
s/\<world\>/bar/g

しかし、私はこの文書をこのように冗長に説明するのではなく、できるだけ読むことができるようにしたいと思います。

sedフルワードのみを一致させるコマンドラインオプションはありますか?もちろん、コマンドラインを編集する別の方法(sedを実行する前にコマンドファイルからsedを実行しますか?しかし、複雑な代替エントリを解析するのが心配です)があれば良いでしょう。

これはUbuntu 22.04のGNU sedです。

答え1

sedまず、Linuxシステムのデフォルト値(GNU)を実行している場合は、使い方をsed簡素化することも\bでき\>ます\<。これにより、理解しやすくなります。

$ cat subs.sed 
s/\bhello\b/foo/g
s/\bworld\b/bar/g

つまり、説明したように実行することはできませんが、回避策は次のとおりです。ファイルはそのまま残りますが、前処理ステップを追加します。

$ sed -e 's|/|/\\<|' -e 's|/|\\>/|2' subs.sed 
s/\<hello\>/foo/g
s/\<world\>/bar/g

ここでは、2つのコマンドをに渡します。最初のコマンドはのsed最初の項目を置き換え、2番目のコマンドは2番目の項目を置き換えます。エスケープ文字が必要なので、文字通りバックスラッシュで処理するには、別の文字を追加してエスケープする必要があります。次に、2番目のコマンドの最後にあるのは、「この行が2番目に表示された場合はこれを行います」を意味します。たとえば、説明する方が簡単です。//\<//\>\\>\\<\\2

$ echo "......" | sed 's/./A/'
A.....
$ echo "......" | sed 's/./A/2'
.A....
$ echo "......" | sed 's/./A/3'
..A...
$ echo "......" | sed 's/./A/4'
...A..

<()したがって、このコマンドを使用すると、次のことを理解するシェルを使用している限り、実際の置換を実行するための小さなエイリアスを作成できます。プロセスの交換:

$ sed -f <(sed -e 's|/|/\\<|' -e 's|/|\\>/|2' subs.sed) file.txt 
foo you
the bar
helloworld

そして、人生をより簡単にするために、シェルの初期化ファイル(~/.bashrc例:)に次の行を追加してエイリアスを作成できます。

alias mysub="sed -i -f <(sed -e 's|/|/\\<|' -e 's|/|\\>/|2' /path/to/subs.sed)"

新しい端末を開くと、実行してmysub file期待される出力を得ることができます。

関連情報