SED正規表現と非欲張りな一致(Perlの.*?エミュレート)

SED正規表現と非欲張りな一致(Perlの.*?エミュレート)

最初の文字列と2番目の文字列の間の文字sed列を置き換えるために使用したいと思います。AB最初発生AC(含む)XXX

~のためはい、次の文字列があります(この文字列はテストにのみ使用されます)。

ssABteAstACABnnACss

私は次のような出力が欲しいssXXXABnnACss


私はこれを使ってこれをしましたperl

$ echo 'ssABteAstACABnnACss' | perl -pe 's/AB.*?AC/XXX/'
ssXXXABnnACss

しかし、私はそれを達成するためにそれを使用したいと思いますsed。次(Perl互換正規表現を使用)は機能しません。

$ echo 'ssABteAstACABnnACss' | sed -re 's/AB.*?AC/XXX/'
ssXXXss

ベストアンサー1

Sed 正規表現は、最も長い一致と一致します。 Sedはnon-greedyと同等の機能はありません。

私たちがしなければならないことは一致するものです

  1. AB
    続いて
  2. 除くすべてのAC数量
  3. AC

残念ながらsed#2は実行できません。少なくとも複数文字の正規表現では実行できません。もちろん、単一文字の正規表現@()の場合はこれまたはを[123]実行できます。したがって、sedのすべての項目を変更してから検索してsedの制限を解決できます。[^@]*[^123]*AC@

  1. AB
    続いて
  2. @除く
    すべて
  3. @

このように:

sed 's/AC/@/g; s/AB[^@]*@/XXX/; s/@/AC/g'

最後の部分は一致しない@バックインスタンスをAC

ただし、入力にすでに文字が含まれている可能性があるため、これは無謀なアプローチです@。だからそれらを一致させることで、私たちは偽の肯定を得ることができます。ただし、NUL()文字はシェル変数に含まれていないため、\x00NULは上記の回避策で代わりに使用するのに最適な文字かもしれません@

$ echo 'ssABteAstACABnnACss' | sed 's/AC/\x00/g; s/AB[^\x00]*\x00/XXX/; s/\x00/AC/g'
ssXXXABnnACss

NULを使用するにはGNU sedが必要です。 (GNU機能を有効にするには、ユーザーはシェル変数POSIXLY_CORRECTを設定しないでください。)

-zNULで区切られた入力(出力など)を処理するためにGNUフラグと一緒にsedを使用すると、find ... -print0NULはパターンスペースには表示されず、NULは置き換えるのに最適です。

printfNULはbash変数には表示できませんが、コマンドに含めることができます。入力文字列にNULを含む任意の文字を含めることができる場合は、次を参照してください。Stefan Chazerasの答えこれはきちんとしたエスケープ方法を追加します。

おすすめ記事