うまく動かないようです。 GNU sedのドキュメントでは、パイプをエスケープするように言われていますが、これは機能しません。また、エスケープなしでストレートパイプを使用することもできません。括弧を追加しても違いはありません。
$ echo 'cat
dog
pear
banana
cat
dog' | sed 's/cat|dog/Bear/g'
cat
dog
pear
banana
cat
dog
$ echo 'cat
dog
pear
banana
cat
dog' | sed 's/cat\|dog/Bear/g'
cat
dog
pear
banana
cat
dog
デフォルトではsed
は POSIX基本正規表現 を使用し、 |
代替演算子が含まれていません。 GNUおよびFreeBSDを含む)sed
の多くのバージョンは、 拡張正規表現 への切り替えをサポートしています。含む|
代替。方法はさまざまです: GNU sedは-r
を使用しますが、 FreeBSD 、 NetBSD 、 OpenBSD 、および OS X sed は-E
を使用します。他のバージョンでは、ほとんどサポートされていません。次を使用できます。
echo 'cat dog pear banana cat dog' | sed -E -e 's/cat|dog/Bear/g'
これらのBSDシステムで動作し、GNUではsed -r
になります。
GNU sed
は-E
を完全に文書化されていませんが実際にサポートされているようです。そのため、上記に限定されたマルチプラットフォームスクリプトがある場合は、それが最良のオプションです。それが文書化されていないので、あなたはおそらく本当にそれに頼ることはできません。
コメントには、BSDバージョンがドキュメント化されていないエイリアスとして-r
もサポートしていることが記載されています。 OS Xはまだ今日ではなく、私がアクセスできる古いNetBSDおよびOpenBSDマシンもできませんが、NetBSD 6.1はできます。私が普遍的に到達できる商用ユニスはありません。したがって、この時点で移植性に関する質問はかなり複雑になっていますが、簡単な答えは、必要に応じて _awk
に切り替えることです。どこでもEREを使用します。
これは、(a|b)
は、拡張正規表現であり、基本正規表現ではありません。使用 -E
これに対処するオプション。
echo 'cat
dog
pear
banana
cat
dog'|sed -E 's/cat|dog/Bear/g'
sed
manページから:
-E Interpret regular expressions as extended (modern) regular expressions rather than basic regular expressions (BRE's).
ご了承ください -r
は同じものの別のフラグですが、-E
はより移植性が高く、POSIX仕様の次期バージョンにも含まれる予定です。
これを行うためのポータブルな方法-より効率的な方法-はアドレスを使用することです。あなたはこれを行うことができます:
printf %s\\n cat dog pear banana cat dog |
sed -e '/cat/!{/dog/!b' -e '};cBear'
このように、行に文字列catが含まれておらず、文字列dogが含まれていない場合、スクリプトからsed
b
ranches、現在の行を自動印刷し、次の行をプルして次のサイクルを開始します。したがって、次の命令は実行されません。この例では、c
hangによって行全体が読み取られますBearが、何でも実行できます。
また、sed
コマンドの!b
に続くステートメントは、文字列dog
またはcat
のいずれかを含む行でonly一致できるため、さらに実行できることにも注意してください。一致しない行に一致する危険性のないテスト。つまり、どちらか一方のみにルールを適用できるようになります。
しかし、それは次です。上記のコマンドの出力は次のとおりです。
###OUTPUT###
Bear
Bear
pear
banana
Bear
Bear
逆参照付きのルックアップテーブルを移植可能に実装することもできます。
printf %s\\n cat dog pear banana cat dog |
sed '1{x;s/^/ cat dog /;x
};G;s/^\(.*\)\n.* \1 .*/Bear/;P;d'
この単純な例の場合、設定するのははるかに手間がかかりますが、長期的には、より柔軟なsed
スクリプトを作成できます。
最初の行で、ex
changeホールドスペースとパターンスペースを保持し、次にex
changeする前に、ホールドスペースに文字列<space>
cat<space>
dog<space>
を挿入します。
それ以降、次のすべての行で、G
etはパターンスペースに追加されたスペースを保持し、行の先頭から最後に追加した改行までのすべての文字が、スペースで囲まれた文字列と一致するかどうかを確認します。もしそうなら、ロット全体をBearで置き換えます。そうでない場合、パターンスペースで最初に出現する改行までP
rintだけなので、害はありません。次に、すべてd
eleteします。
###OUTPUT###
Bear
Bear
pear
banana
Bear
Bear
そして、私が柔軟と言うとき、それはそれを意味します。ここでは、catをBrownBearに置き換え、dogをBlackBear:
printf %s\\n cat dog pear banana cat dog |
sed '1{x;s/^/ 1cat Brown 2dog Black /;x
};G;s/^\(.*\)\n.* [0-9]\1 \([^ ]*\) .*/\2Bear/;P;d'
###OUTPUT###
BrownBear
BlackBear
pear
banana
BrownBear
BlackBear
もちろん、ルックアップテーブルの内容を大幅に拡張できます。90年代に、彼がどのようにして粗い計算機を構築したかを説明したときに、この件について Greg Ubben's usenet emailsからアイデアを見つけました。単一のsed s///
ステートメントから。
これはかなり古い質問ですが、誰かが試したい場合に備えて、sedファイルを使用してsedでこれを行うためのかなり簡単な方法があります。各オプションは別々の行にリストすることができ、sedはそれぞれを評価します。 orと論理的に同等です。たとえば、特定のコードを含む行を削除するには:
あなたは言うことができます:sed -E '/^\/\*!(40103|40101|40111).*\/;$/d'
またはこれをsedファイルに入れます:
/^\/\*!40103.*\/;$/d
/^\/\*!40101.*\/;$/d
/^\/\*!40111.*\/;$/d
以下は、sed
の実装固有のオプションを使用しない手法です(-E
、-r
など)。パターンを単一の正規表現cat|dog
として記述する代わりに、sed
を2回実行するだけです。
echo 'cat
dog
pear
banana
cat
dog' | sed 's/cat/Bear/g' | sed 's/dog/Bear/g'
これは明らかな回避策ですが、共有する価値があります。当然、2つ以上のパターン文字列に一般化されますが、sed
の非常に長いチェーンは見栄えがよくありません。
私はsed -i
(これはすべての実装で同じように機能します)を使用してファイルを変更します。ここでは、一時的な結果がそれぞれファイルに保存されるため、パターン文字列の長いリストを適切に組み込むことができます。
for pattern in cat dog owl; do
sed -i "s/${pattern}/Bear/g" myfile
done