web-dev-qa-db-ja.com

正規表現で後方参照を出力する

私は、sedに(一致だけでなく)行全体を置換に置き換える方法を望んでいたので、次のようなことができました。

sed -e "/$some_complex_regex_with_a_backref/\1/"

後方参照のみを印刷するようにします。

この質問 から、それを行う方法は、行全体に一致するように正規表現をいじくり回すか、他のツール(Perlなど)を使用することのようです。 regex.*regex.*に変更するだけでは、常に機能するとは限りません(その質問で述べたように)。例えば:

$ echo $regex
\([:alpha:]*\)day

$ echo $phrase
it is Saturday tomorrow

$ echo $phrase | sed "s/$regex/\1/"
it is Satur tomorrow

$ echo $phrase | sed "s/.*$regex.*/\1/"

$ # what I'd like to have happen
$ echo $phrase | [[[some command or string of commands]]]
Satur

私はこれを行うための最も簡潔な方法を次のことを前提として探しています。

  • 正規表現は変数内にあるため、ケースバイケースで変更することはできません。
  • Perlや他のより強力な言語を使用せずにこれを実行したいと思います。
6
jakesandlund

[〜#〜] so [〜#〜] でもこの質問をし、探していたものを実行するpotongから this の回答を得ました。

sed '/'"$regex"'/!b;s//\n\1\n/;s/.*\n\(.*\)\n.*/\1/' file

$regexの内容に関する知識に依存しないことに注意してください。後で行全体を後方参照のみに置き換えるために、改行を番兵値として使用します。

0
jakesandlund

答えるのに十分なsedはわかりませんが、柔軟性があり、grepを使用している場合:

grep --only-matching "complex_regex" file

または

grep -o "complex_regex" file

-only-matching(または短縮形-o)フラグは、行全体ではなく、一致した部分のみを出力するようにgrepに指示します。

4
Hai Vu

最初の。*は「日」で停止し、後方参照は空のままです。後方参照の[[:alpha:]]の前に一致する明確なものが必要です。例えば空間、

$ echo $regex
\([[:alpha:]]*\)day

$ echo $phrase
it is Saturday tomorrow

$ echo $phrase | sed "s/.* $regex.*/\1/"
Satur

私は正規表現が好きで嫌いです。


編集:

単語境界の非POSIX拡張機能(\ b)は、両方のケースをキャッチしているようです。

$ regex="\b\([[:alpha:]]\+\)day\b"

パターンが複数回出現する状況や、パターンに複数の単語が含まれている場合の対処方法がわかりません。

$ cat phrase.txt
it is Saturday tomorrow
it is   Saturday tomorrow
Saturday is the date tomorrow
        Saturday is the date tomorrow
Saturday is the day tomorrow
        Saturday is the day tomorrow
Saturday is the day in dayton tomorrow
        Saturday is the day in dayton tomorrow
Saturday is the day after Friday
The last day of the week is Friday

$ cat phrase.txt | sed -e "s/.*$regex.*/\1/"
Satur
Satur
Satur
Satur
Satur
Satur
Satur
Satur
Satur
Fri

Sed-fuをもっと持っている人がもっと良い答えをくれるかどうか知りたいです。 :-)

0
mgjk

これはmgjkの答えに近いですが、境界マッチングへのアプローチが少し異なります。

echo $phrase | sed 's/.*[^[:alpha:]]\([[:alpha:]]*\)day.*/\1/'
Satur

.*は何でも飲み込みます。最初に「not必要な文字」と一致させ、次に「必要な文字」と一致させる必要があります。だから、$regex保存できます

[^[:alpha:]]\([[:alpha:]]*\)day

癖がないわけではありませんが(「土曜日」が最初の行の場合は正しい形式では機能しません)、より強力なツールの代わりにsedだけを使用するように設定されている場合は、それで十分かもしれません。 。 「行の始まり」の問題を解決するために、2つの部分からなる正規表現を使用してそれを行うこともできますが、その後、再び複雑になり始めます。これは望ましくありません。基準が変更された場合、多くの解決策が存在します。

0