コマンドファイルに代替リストを保持したいと思います。
subs.sed
s/hello/foo/g
s/world/bar/g
私はこのように動作します。sed -i -f subs.sed file.txt
file.txt
からhello world
。foo 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
期待される出力を得ることができます。