周辺文字を印刷せずに「sed」に一致する正規表現を抽出する

周辺文字を印刷せずに「sed」に一致する正規表現を抽出する

すべての「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.  

PS:「sed」でこれを実装する方法についてのフィードバックをいただきありがとうございます。私は「grep」と「awk」を使ってこれを行う方法を知っています。 「sed」の(制限的ですが)理解に穴があり、「sed」でこれを行う方法があるかどうか疑問に思います。 1つの点は
単に無視されました。

答え1

正規表現にグループが含まれている場合は、文字列を一致させる方法がいくつかあります。グループを含む正規表現はあいまいです。たとえば、正規表現と^.*\([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'

より一般的には、正規表現の最初の項目を抽出するには、その正規表現の否定を計算する必要があります。理論的には常に可能ですが、否定の大きさは否定されるべき正規表現の大きさに応じて指数関数的に大きくなるため、これはしばしば非実用的です。

他の例を考えてみましょう。

sed -n 's/.*\(CONFIG_[a-zA-Z0-9_]*\).*/\1/p'

この例は実際には同じ問題を示していますが、一般的な入力ではこれを見ることはできません。これを入力すると、上記のコマンドが代わりにhello CONFIG_FOO_CONFIG_BAR印刷されます。CONFIG_BARCONFIG_FOO_CONFIG_BAR

sedを使用して最初の一致を印刷する方法がありますが、少しトリッキーです。

sed -n -e 's/\(CONFIG_[a-zA-Z0-9_]*\).*/\n\1/' -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

答え2

そうではありませんが、sedしばしば見落とされている1つの事実は、grep -o私の考えでは、これが仕事のためのより良いツールであるということです。

たとえば、CONFIG_カーネル構成からすべてのパラメーターを取得するには、次のようにします。

# grep -Eo 'CONFIG_[A-Z0-9_]+' config
CONFIG_64BIT
CONFIG_X86_64
CONFIG_X86
CONFIG_INSTRUCTION_DECODER
CONFIG_OUTPUT_FORMAT

連続した数値シーケンスを取得するには:

$ grep -Eo '[0-9]+' foo

答え3

sed '/\n/P;//!s/[0-9]\{1,\}/\n&\n/;D'

n...右の代替フィールドでは、sの代わりに文字通り改行文字が必要になる場合がありますが、問題なくこれを行います。ただし.*CONFIG、この方法はオンラインに一致する項目が1つしかない場合にのみ機能します。それ以外の場合は、常に最後の一致のみを取得します。

あなたは見ることができますこれどのように動作するかについて説明しますが、これは1行で発生したのと同じ数の一致のみを別々の行に印刷します。

同じ戦略を使用して、連続して第2の[num]項目を取得することができます。たとえば、CONFIG一致のみを印刷したい場合(1行目から3番目の一致のみ):

sed '/\n/P;//d;s/CONFIG[[:alnum:]]*/\n&\n/3;D'

...CONFIG各文字列が英数字ではなく、1つ以上の文字で区切られていると仮定しても。

私の考えでは - 数字の場合 - これも動作するようです:

sed -n 's/[^0-9]\{1,\}/\n/g;s/\n*\(.*[0-9]\).*/\1/p

...右手については以前と同じ警告です\n。これは最初のものよりはるかに高速ですが、明らかに普遍的には適用できません。

CONFIG の場合、P;...;D上記のループをパターンと共に使用するか、次のようにすることができます。

sed -n 's/[^C]*\(CONFIG[[:alnum:]]*\)\{0,1\}C\{0,1\}/\1\n/g;s/\(\n\)*/\1/g;/C/s/.$//p'

...これは少し複雑で、sed正しく整列された参照優先順位に従って機能します。また、1 行のすべての CONFIG 一致を一度に分離します。以前と同じ仮定をしますが、各CONFIG一致は英数字以外の1つ以上の文字で区切られています。 GNUでは、次のようにsed書くことができます。

sed -En 's/[^C]*(CONFIG\w*)?C?/\1\n/g;s/(\n)*/\1/g;/C/s/.$//p'

関連情報