カンパ〜イ!←最初の1杯目、なに頼む?

hp-uxのコマンドで困っております。
どなたか知恵をお貸しいただけたらと思います。

あるファイルより条件に合致する特定の文字列の置換を行い別のファイルとして保存したいと考えております。
このときに以下のsedのコマンドを利用しているのですが、一部上手くいかなくて難儀しております。

コマンド(※文字列の前後にわかりやすく<>を付けていますが実際には入力しません)
sed "/<文字列(1)>[^0-9]/"s"/<文字列(1)>/<文字列(2)>/"g aaaa.txt > bbbb.txt

コマンドの内容
aaaa.txtの中を検索し文字列(1)かつ文字列(1)のすぐ後ろの文字が数字でない場合(例えばIPアドレスで10.xxx.xxx.1というIPアドレスを置換したい場合に10.xxx.xxx.10や10.xxx.xxx.100を含めないようにする場合です)、文字列(1)を文字列(2)に置換しbbbb.txtに保存する。
(※上記コマンドのみだと条件に合致する文字列のたびにbbbb.txtが上書きされるため一番最後の条件に合致する文字列しか置換されませんので、実際にはコマンドのたびにbbbb.txtをaaaa.txtに上書きコピーするステップを入れています)

この際、困っておりますのが元ファイルaaaa.txtにある各行の文字列が以下の場合に認識がされず置換が行われない点です。
(1)10.xxx.xxx.1<タブ>xxxxxxxxxの場合(※条件に合致する文字列のすぐ後ろにタブ文字が入っている場合)
(2)10.xxx.xxx.1<改行>の場合(※条件に合致する文字列のすぐ後ろが改行となっており同一行にそれ以上文字が存在しない場合)

上記の(1),(2)のような行は置換が行われず、元の値のままとなってしまいます。
これらを解決する方法がありましたらよろしくお願いいたします。

A 回答 (1件)

> 10.xxx.xxx.1<タブ>xxxxxxxxxの場合



こちらはタブが[^0-9]にマッチするはずなのですが。

> 10.xxx.xxx.1<改行>

こちらの対策は、「<文字列(1)>のあとが、数字でないか、行末かのどちらかである」ということで
/<文字列(1)>\([^0-9]\|$\)/
でいいはずです。


気になるのは
○ ダブルクオートを使っていること。
$等のsedで使う文字がシェル側で展開されてしまいます。

○ 文字列(1) がIPアドレスになっていること。
もし、そのまま入力していたら、 . が「任意の文字列」を意味するメタ文字と解釈されています。
10.20.1.5[^0-9] で検索したら 10.20.165.3 でもマッチします。

○ 1行に複数あった場合、意図しない置換される可能性がある。
10.xxx.xxx.10 10.xxx.xxx.1
とあって、10.xxx.xxx.1 → 20.xxx.xxx.2 に置換したい場合
/10\.xxx\.xxx\.1[^0-9]/ → この行はマッチする
s/10\.xxx\.xxx\.1/20.xxx.xxx.2/g
→ 10\.xxx\.xxx\.1にマッチする全てを置換
→20.xxx.xxx.20 20.xxx.xxx.2

解決例
s/10\.xxx\.xxx\.1\([^0-9]\|$\)/20.xxx.xxx.2\1/g
グルーピングを使って、直後の文字を記憶→後で\1で参照することで
「文字列(1)+後の文字 → 文字列(2)+後の文字」という置換を行う

○ aaaa.txtを上書きする必要はない。
パイプを使って
sed コマンド1 aaaa.txt | sed コマンド2 | ... | sed コマンドn > bbbb.txt

-eオプションで複数のコマンドが指定できる
sed -e コマンド1 -e コマンド2 ... -e コマンドn aaaa.txt > bbbb.txt

コマンドはセミコロンで区切って複数記述できる。
素に書くとシェルのコマンド区切りと解釈されるので、全体をクオートする等の必要がある。
sed 'コマンド1;コマンド2; ...;コマンドn' aaaa.txt > bbbb.txt
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報