2016-07-03 7 views
1

POSIXシェルスクリプトでは、{{}}に囲まれたすべてのテキストを検索し、その中括弧に沿ってテキストをアスタリスクに置き換える必要があります。例えば開始区切り文字と終了区切り文字の間で、テキストに終了区切り文字(つまり貪欲でない一致)が含まれないようにする方法はありますか?

入力が

{{ abc }} def {{ ghi {jkl} mno }} pqr 

であれば、出力は私が働く。このためsedコマンドを思い付くことができていない

* def * pqr 

でなければなりません。

私はいくつかのコマンドを試しましたが、動作しません。たとえば、次のコマンドは、sedが欲張りマッチングを実行するため、目的の出力を生成しません。それはちょうど{{ abc }}の代わりに{{ abc }} def {{ ghi {jkl} mno }}と最初のマッチとしてマッチします。

$ echo "{{ abc }} def {{ ghi {jkl} mno }} pqr" | sed 's/{{.*}}/*/g' 
* pqr 

これはあまり一致しないために機能しない別の例です。文字列のこの部分に}が含まれているため、{{ ghi {jkl} mno }}(一致させたい)と一致しません。

$ echo "{{ abc }} def {{ ghi {jkl} mno }} pqr" | sed 's/{{[^}]*}}/*/g' 
* def {{ ghi {jkl} mno }} pqr 

他にどのようにこのような対応ができますか?

私はNon greedy regex matching in sed?を経ていますが、ここで私は2つの連続した文字の特定のシーケンス、すなわち}}除く{{}}の間のすべてを一致させたいので、解決策はあり役に立ちません。 1文字以外の区切り文字の間にすべて一致するものを試そうとすると、その質問に対する回答が助けになりました。

答えて

0

"}}"が含まれていないものと一致する正規表現がある場合は、"{{" exp "}}"として使用できます。残念ながらsedには補数正規表現演算子がありません。正規表現の補完は規則的であるため、多くの正規表現の実装はそうしています。だから我々はそれが存在することを知っているが、我々はそれを手動で構築しなければならない。

sedより読みやすい形式では、近いものは"{{" ([^}]* ("}" [^}])?)* "}}"です。

で適切 sed

$ echo "{{ abc }} def {{ ghi {jkl} mno }} pqr" \ 
    | sed 's/{{\([^}]*\(}[^}]\)\?\)*}}/*/g' 
* def * pqr 
$ 

これはあなたが行に3つのブレースを期待しているかどうかに依存したい正確に何ではないかもしれません。このabc {{ def { ghi }}}はどうすればよいですか?ブレースのバランスを実際に調整する必要がある場合は、これを通常の言語の領域から文脈自由な言語に置き換え、より強力なツールが必要になります。

ユーザー名を指定すると、形式的な言語とオートマトンの理論に関する本を読むことができます。それは "古い"技術かもしれないが、それは非常に強力であり、あらゆる種類の技術によって一日中使われている。

関連する問題