sedの正規表現文字をエスケープして、正規表現文字として解釈する必要があるのはなぜですか?


11

例えばそうです
cat sed_data.txt | sed 's/\b[0-9]\{3\}\b/NUMBER/g'
、私がすることをしなければならない正規表現を形成するために、文字をエスケープします。この場合、何度も解釈されるために中括弧をエスケープする必要がありました。
どうして?エスケープされない限り、すべてが正規表現文字になると期待していました。すなわち反対です。


多少、ショートバージョンが、「それは、コマンドの実装に依存します」というこの質問をカバーすることはVimでの検索についての記事がありました... unix.stackexchange.com/questions/90345/...
Dravスローン

@DravSloan:それが同じかどうかはわかりません.Vim ではデフォルトでテキストを検索し、エスケープして正規表現を検索する必要がありますが、この場合、フォーマットはs/regex//gすでに正規表現を想定しており、必要なテキストであると予想しますエスケープされる
ジム

回答:


14

これは、おそらくPerlや友人が使用していたERE(拡張正規表現)ではなくsedPOSIX BRE(基本正規表現)を使用するためです。

sed(1)manページから:

REGULAR EXPRESSIONS
       POSIX.2 BREs should be supported, but they aren't completely because of
       performance problems.  The \n sequence in a regular expression  matches
       the newline character, and similarly for \a, \t, and other sequences.

上記のリンクからの関連する引用:

基本正規表現またはBREフレーバーは、従来のUNIX grepコマンドで使用されるフレーバーと同様のフレーバーを標準化します。これは、現在も使用されているかなり古い正規表現フレーバーです。このフレーバーを際立たせることの1つは、ほとんどのメタキャラクターがメタキャラクターにフレーバーを与えるためにバックスラッシュを必要とすることです。POSIX EREを含む他のほとんどのフレーバーは、バックスラッシュを使用してメタ文字の意味を抑制します。

クレイグ・サンダースのコメントから逐語的に引用:

GNU sedでは少なくとも、sedに-rまたは--regexp-extendedコマンドラインオプションを指定して拡張正規表現を使用するように指示できます。これは、sedスクリプトが過度にエスケープされて醜くなりたくない場合に便利です。


1
注GNUに少なくともsedのことを、あなたが拡張正規表現を使用するようにsedを伝えることができる-rか、--regexp-extendedコマンドラインオプション。これは、sedスクリプトが過度にエスケープされて醜くなりたくない場合に便利です。
cas

@CraigSandersこれをありがとう。回答に追加されました。
Joseph R.

@CraigSanders、他のsed実装(それらがEREをサポートする場合、主にBSD)は-E、代わりにそれを使用する傾向があります(これはと同じオプションであるため、はるかに理にかなっていますgrep。なぜGNU sed-r私にとって謎なのかを選択した理由です)。
ステファンChazelas

ええ、私にとっても謎です。-Eを使用する方が理にかなっています。そして、GNU grepに一致するように-F、-G、および-Pを追加します。IMO gawkも同じRE引数の恩恵を受けます...または、少なくとも-P。
cas

12

それは歴史的な理由によるものです。

Regexpはed、70年代初頭にユーティリティでUnixに最初に導入されました。しかしがedに基づいていたqed、実装が同じ著者によって、より複雑な正規表現を理解し、ed唯一の理解^$[...].*および\上記のすべてをエスケープします。

さて、より多くの演算子を持つ必要が生じたとき、後方互換性を壊すことなくそれらを導入する方法を見つけなければなりませんでした。スクリプトを使用するために使用した場合s edのようにコマンドをs/foo() {/foo (var) {/gすべてのインスタンス置き換えることfoo() {としfoo(var) { 、あなたが導入された({をオペレータに、それはそのスクリプトを破ります。

ただし、それはRE演算子ではなかったs/foo\(\) {/foo\(var\) {/ので同じs/foo() {/foo(var) {/であり、エスケープする理由がなかったため、スクリプトは実行し(ませんでした。したがって、新しい\(or \{演算子を導入しても下位互換性は損なわれません。古い構文を使用して既存のスクリプトを壊す可能性は非常に低いからです。

だから、それが行われたことです。その後、\(...\)唯一のために最初に追加されましたs edようなことを行うには、コマンドs/foo\(.\)/\1bar/以降としてgrep '\(.\)\1'(しかし、好きではないものを土台\(xx\)*)。

(その約10年後の1979年、)UnixV7では、正規表現の新しい形、新しい中に追加されましたegrepし、awk(彼らは新しいツールであるため、壊れすべき下位互換性はありません)拡張正規表現と呼ばれるユーティリティ。最後に、それはケン・トンプソンの古代で利用可能な機能を提供するqed(選択演算子|、グループ化(..)*)など、いくつかの演算子を追加+し、?(基本的な正規表現の後方参照の機能を持っていませんでした)。

後のBSDを添加\<し、\>(BREとEREの両方に)、およびSysVを加え\{\}のみBREではします。

このような下位互換性の破壊により、{それ}はEREに追加されてからかなり遅くなりました。誰もがそれを追加したわけではありません。たとえば、awkバージョン4.0.0(2011)までのGNUは、{POSIX準拠モードに強制されない限りサポートしませんでした。

GNU grepが90年代の初めに書かれたとき、それはBSDとSysVの両方からすべての利点を追加しました(\<、など{)。(?{+(他のBREの実装と互換性があるように)バックスラッシュが先行されなければなりません。それはあなたが行うことができます理由です.\+GNUにgrep(つまり、POSIXではないか、他の実装でサポートされているが)、あなたが行うことができます(.)\1GNUでegrep(つまり、POSIXではないか、GNUを含む多くの他の実装でサポートされているがawk)。

\x演算子の追加は、下位互換性のある方法で演算子を追加する唯一の方法ではありません。たとえば、perl使用され(?...)ます。(?=...)EREでは無効であるため、これはEREとの下位互換性があります.*?vim同様の事業者の場合は、\@=または.\{-}を導入するなどして、別の方法で行いました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.