title=
テキストファイルの文字列の前後にスペースが表示されている場合にのみsedを使用してスペースを下線に置き換える方法" "
たとえば(テキストファイルの行):
title="This is the title of my book" img=scr " </header><!-- .entry-header -->
title="Today is a beautiful day" img=scr " </header><!-- .entrrrrkkky-header -->
sed 後、テキストファイルの変更が必要です。
title="This_is_the_title_of_my_book" img=scr " </header><!-- .entry-header -->
title="Today_is_a_beautiful_day" img=scr " </header><!-- .entrrrrkkky-header -->
デフォルトでは、文字列の後にスペースがある場合にのみaが置き換えられます。
_
" "
title=
テキストファイルの名前は任意です。file.txt
答え1
ループでこれを行う必要があります。
s/\(^.*title="[^" ]*\) \([^"]*".*$\)/\1_\2/
または(すばやく)
s/\(title="[^" ]*\) \([^"]*"\)/\1_\2/
または(おそらくもう一度速くなるでしょう。なぜ自分を置き換えるために別の一致を追加する必要がありますか?!)
s/\(title="[^" ]*\) /\1_/
そして、もはや変更がなくなるまで、sedのテストと分岐機能を使用して代替をやり直してください。このコマンドのパターンのポイントは、最初の(残りの)スペースから行を分割し、そのスペースを下線に置き換えることです。
以下はスクリプトです。
#!/bin/sh
sed -e ':loop' \
-e 's/\(title="[^" ]*\) \([^"]*"\)/\1_\2/' \
-e 't loop' <foo.in >foo.out
diff -u foo.in foo.out
もともと答えはより広いパターンを使用していましたが、@g-manはこれが必要ではないと述べました。 10Mbファイルのsedタイミングでわかるように、遅くなります(Debian 7でGNU sedでテスト)。
$ ./foo1
27.03user 0.01system 0:27.18elapsed 99%CPU (0avgtext+0avgdata 1104maxresident)k
0inputs+0outputs (0major+333minor)pagefaults 0swaps
9.54user 0.00system 0:09.60elapsed 99%CPU (0avgtext+0avgdata 972maxresident)k
0inputs+0outputs (0major+301minor)pagefaults 0swaps
OSXの場合、違いはそれほど大きくありません。
$ ./foo1
real 0m11.943s
user 0m11.897s
sys 0m0.024s
real 0m5.858s
user 0m5.839s
sys 0m0.014s
興味深いことに、より広いモードはSolarisのsedでは動作しません(ただし、より短いモードは動作します)。 BSDとGNUの両方が一致しますが、グループ内の行の終わり\(
や\)
グループ内の行の終わりと一致しません。同様に、HPUX 11.31およびAIX 7.1でも動作します。
POSIX sed は BRE を使用し、グループ化機能は以下で提供されます。9.3.6 複数の文字を一致させるBRE:
"\("
サブ式は文字ペアと 。間にサブ式を囲むことでBREで定義できます"\)"
。これらのサブ式は、サブ式の固定がオプションの動作でない限り、「(」および「)」なしで一致するすべての項目と一致する必要があります。BRE表現アンカー。サブ式は任意に入れ子にすることができます。
9.3.8 BRE表現の固定用語を説明してください。
BREは、行で始まるか終わる一致する文字列に制限できます。これを「アンカリング」といいます。
したがって、標準実装の文脈では、これはSolarisの既知の制限であり、sed
標準ではこれを「オプションの」動作として許可します。
追加資料:
- 3.7 sed マスターコマンド(ラベルとループ説明)