そこにいるすべての「sed」医師へ:
行で一致した正規表現を抽出するために「sed」を取得するにはどうすればよいですか?
つまり、通常の
式に対応する文字列だけで、含まれている行の一致しない文字がすべて削除されている必要があります。
以下のような後方参照機能を使ってみました
regular expression to be isolated
gets `inserted`
here
|
v
sed -n 's/.*( ).*/1/p
これは
のようないくつかの表現で機能します sed -n 's/.*(CONFIG_[a-zA-Z0-9_]*).*/1/p
これは、「CONFIG_…。」(一部の「* .h」ファイルにあります)で始まるすべてのマクロ名をきちんと抽出し、それらをすべて1行ずつ出力します
CONFIG_AT91_GPIO
CONFIG_DRIVER_AT91EMAC
.
.
CONFIG_USB_ATMEL
CONFIG_USB_OHCI_NEW
.
e.t.c.
しかし、上記は次のようなものに分類されます
sed -n 's/.*([0-9][0-9]*).*/1/p
これは常に
のように1桁を返します 7
9
.
.
6
などの連続した数値フィールドを抽出するのではなく
8908078
89670890
.
.
.
23019
.
e.t.c.
追伸:これが「sed」でどのように達成されるかについてフィードバックをいただければ幸いです。
「grep」と「awk」を使用してこれを行う方法を知っています。制限付き–
'sed'の理解には穴があり、
私が単に見落としていた'sed'でこれを行う方法があるかどうか。
承認された回答:
正規表現にグループが含まれている場合、文字列をそれに一致させる方法は複数ある可能性があります。グループを持つ正規表現はあいまいです。たとえば、正規表現^.*([0-9][0-9]*)$
について考えてみます。 および文字列a12
。 2つの可能性があります:
-
a
に一致.*
に対して および2
[0-9]*
に対して;1
[0-9]
と一致します 。 -
a1
に一致.*
に対して[0-9]*
に対する空の文字列;2
[0-9]
と一致します 。
Sedは、他のすべての正規表現ツールと同様に、最も早い最長の一致ルールを適用します。最初に、最初の可変長部分を可能な限り長い文字列と一致させようとします。文字列の残りの部分を正規表現の残りの部分と一致させる方法が見つかった場合は、問題ありません。それ以外の場合、sedは最初の可変長部分に対して次に長い一致を試行し、再試行します。
ここで、最初に最も長い文字列と一致するのはa1
です。 .*
に対して 、したがって、グループは2
にのみ一致します 。グループを早く開始したい場合は、一部の正規表現エンジンで.*
を作成できます。 貪欲ではありませんが、sedにはそのような機能はありません。したがって、あいまいさを取り除く必要があります いくつかの追加のアンカーがあります。先頭の.*
を指定します 数字で終わらせることはできないため、グループの最初の数字が最初に一致する可能性があります。
-
数字のグループを行の先頭にできない場合:
sed -n 's/^.*[^0-9]([0-9][0-9]*).*/1/p'
-
数字のグループが行の先頭にあり、sedが
?
をサポートしている場合 オプション部品の演算子:sed -n 's/^(.*[^0-9])?([0-9][0-9]*).*/1/p'
-
数字のグループが行の先頭にある可能性がある場合は、標準の正規表現構造に固執します:
sed -n -e 's/^.*[^0-9]([0-9][0-9]*).*/1/p' -e t -e 's/^([0-9][0-9]*).*/1/p'
ちなみに、[0-9]*
を作成するのは、同じ最も早い最長の一致ルールです。 後続の.*
ではなく、最初の数字の後の数字と一致します 。
1行に複数の数字のシーケンスがある場合、最初の.*
に適用される最も早い最長の一致ルールのために、プログラムは常に最後の数字のシーケンスを抽出することに注意してください。 。数字の最初のシーケンスを抽出する場合は、前に来るのが数字以外のシーケンスであることを指定する必要があります。
sed -n 's/^[^0-9]*([0-9][0-9]*).*$/1/p'
より一般的には、正規表現の最初の一致を抽出するには、その正規表現の否定を計算する必要があります。これは常に理論的には可能ですが、否定のサイズは、否定する正規表現のサイズに応じて指数関数的に大きくなるため、多くの場合、これは実用的ではありません。
関連:外付けハードドライブのSMARTサポートを有効にできませんか?他の例を考えてみましょう:
sed -n 's/.*(CONFIG_[a-zA-Z0-9_]*).*/1/p'
この例は実際には同じ問題を示していますが、通常の入力では見られません。フィードする場合hello CONFIG_FOO_CONFIG_BAR
、次に上記のコマンドはCONFIG_BAR
を出力します 、CONFIG_FOO_CONFIG_BAR
ではありません 。
sedで最初の一致を印刷する方法はありますが、少し注意が必要です:
sed -n -e 's/(CONFIG_[a-zA-Z0-9_]*).*/n1/' -e T -e 's/^.*n//' -e p
(sedがn
をサポートしていると仮定します s
の改行を意味します 置換テキスト。)これは、sedが正規表現の最も早い一致を検索し、CONFIG_…
の前にあるものと一致させようとしないために機能します。 少し。行内に改行がないため、一時的なマーカーとして使用できます。 T
コマンドは、先行するs
の場合、あきらめるように指示します コマンドが一致しませんでした。
sedで何かを行う方法がわからない場合は、awkを使用してください。次のコマンドは、正規表現の最も早い最長一致を出力します。
awk 'match($0, /[0-9]+/) {print substr($0, RSTART, RLENGTH)}'
また、シンプルにしたい場合は、Perlを使用してください。
perl -l -ne '/[0-9]+/ && print $&' # first match
perl -l -ne '/^.*([0-9]+)/ && print $1' # last match