sedで複数の再利用のために複雑な正規表現をどのように保存しますか?


12

を使用するsed場合、ファイル内で2回一致させる必要があるかなり複雑で複雑な正規表現を作成することがよくあります。この正規表現を保存して2回参照する方法はありますか?

たぶんこんな感じ?

sed ' complicated_regex=/^(([a-f0-9]{32})+([a-zA-Z0-9=]{{$i}})?)+$/
s/complicated_regex:complicated_regex/simple-output/
' my_file

更新:回答により、bash変数を使用するソリューションが提示されました。これは機能しません。与えられたtest.txt

#test.txt
foo bar
bar foo

そしてスクリプト

#!/bin/bash

VALUE='foo \([a-z]\+\)'

sed 's/"${VALUE}"/foo happy \1/' test.txt

これは出力を生成するはずです

foo happy bar
bar foo

しかし、代わりにエラーが発生します

sed: -e expression #1, char 24: invalid reference \1 on `s' command's RHS

あなたはPerlを使用する場合は、式の中の式の前の部分を参照することができますperl -pe 's/^(([a-f0-9]{32})+([a-zA-Z0-9=]{{$i}})?)+:\1$/simple_output/' my_file
グレンはジャックマン

1
sedには複雑すぎるものを見つけたときは、awkやperlを試してみてください。
Gilles「SO-邪悪なことをやめなさい」

2
@Cory:構文が正しい場合、例はうまく機能します。あなたはそれがあるべきまだあなたが期待するシェル拡張からそれを隠す「一重引用符」で囲まれた「$変数」を...持っているsed 's/'"${VALUE}"'/foo happy \1/' test.txt
Peter.O

回答:


7

シェル変数を使用できます。

complicated_regex='(([a-f0-9]{32})+([a-zA-Z0-9=]{{$i}})?)+'
sed s/^"$complicated_regex":"$complicated_regex"\$/'simple-output'/ my_file

あなたが何を意味しているのかはわかり$iませんが、単一引用符の外に置く必要があるかもしれません:

complicated_regex='(([a-f0-9]{32})+([a-zA-Z0-9=]{{'"$i"'}})?)+'

もちろん、これはsedコマンドがシェルから呼び出された場合にのみ機能しますが、ほとんどすべてのプログラミング言語で同様の解決策があります。(そして、内で変数を使用することは不可能だと思いますsed。)
StéphaneGimenez '21

Hrm。これを試してみると、後方参照が壊れているように見えます。 s/$complicated_regex/\1/これは無効な参照であることを示すエラーが発生します。
Cory Klein、

ああ、たぶん私のせいです、私はzsh変数置換に慣れています。更新された回答を参照してください。
ステファン・ヒメネス

あなたは変数からアンカーを削除し、sedスクリプトでそれらを配置する必要があります:sed "s/^${complicated_regex}:${complicated_regex}\$/simple-output/" my_file
グレンはジャックマン

ああ!はい、私は、有効な正規表現連結:-)提供されたことをチェックするのを忘れて
ステファン・ヒメネス

0

シェル変数の値をドロップしてsed、残りのsedスクリプトでバックスラッシュエスケープを変更する方法を気にしない最も簡単な方法は、変数を除いてすべてを一重引用符で囲み、それを二重引用符で囲むことです。

次のコード例はすべて、次のことを前提としています。 VALUE='foo \([a-z]\+\)'

変数が展開されていないため、次の壊れたコードは失敗しますVALUE

sed 's/"${VALUE}"/foo happy \1/' test.txt

次の壊れたコードは失敗します。バックスラッシュ\1がシェルによって食べられるためです(シングルクォートではなくダブルクォートでsed囲まれているため)。

sed "s/${VALUE}/foo happy \1/" test.txt

次のコードは期待どおりに動作します。

sed 's/'"${VALUE}"'/foo happy \1/' test.txt

以下のコードも機能します:

sed "s/${VALUE}/foo happy \\1/" test.txt

次のことも行います。

sed s/"${VALUE}"/foo\ happy\ \\1/ test.txt

しかし、なぜ複雑になるのですか?sedスクリプトを一重引用符で囲むと、特にコードを読み取る非シェルスクリプティングの教祖にとって、すべてがより明確になります。私が好む方法は、繰り返しになりますが、変数の展開のためだけに、単一引用符から二重引用符を削除して、単一引用符に戻ります。

sed 's/'"${VALUE}"'/foo happy \1/' test.txt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.