web-dev-qa-db-ja.com

行全体を必要とせず、正規表現からの一致のみ

正規表現から一致を取得するだけです。

$ cat myfile.txt | SOMETHING_HERE "/(\w).+/"

出力は、括弧内で一致したもののみである必要があります。

grepは行全体と一致するため、使用できないと思います。

これを行う方法を教えてください。

15
Alex L

2つのこと:

  • @Roryで述べられているように、_-o_オプションが必要なので、(行全体ではなく)一致のみが出力されます。
  • さらに、_-P_オプションを使用して、Perlの正規表現を使用します。これにはLookhead _(?= )_およびLook behind _(?<= )_、それらはパーツを探しますが、実際にはそれらを一致させて印刷しません。

括弧の内側の部分だけを一致させたい場合:

_grep -oP '(?<=\/\()\w(?=\).+\/)' myfile.txt
_

ファイルに文字列/(a)5667/が含まれている場合、grepは 'a'を出力します。

  • _/(_は_\/\(_によって検出されますが、それらはlook-behind _(?<= )_内にあるため、レポートされません
  • aは_\w_と一致し、したがって表示されます(_-o_のため)
  • _)5667/_が見つかりますb <_\).+\/_ですが、それらはlook-ahead _(?= )_に含まれているため、レポートされません
12
DrYak

使用 -oオプション(grep)。

例えば:

$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar
18
Rory
    sed -n "s/^.*\(captureThis\).*$/\1/p"

-n      don't print lines
s       substitute
^.*     matches anything before the captureThis 
\( \)   capture everything between and assign it to \1 
.*$     matches anything after the captureThis 
\1      replace everything with captureThis 
p       print it
6
Joshua

括弧内にあるものだけが必要な場合は、サブマッチのキャプチャをサポートするものが必要です(名前付きまたは番号付きのキャプチャグループ)。 Perlとsedではできますが、grepやegrepではできません。たとえば、Perlの場合:

Fooというファイルに次のような行がある場合:

/adsdds      /

あなたがやる:

Perl -nle 'print $1 if /\/(\w).+\//' foo

文字aが返されます。それはあなたが望むものではないかもしれません。何を一致させようとしているのかを教えていただければ、より良い支援を受けることができます。 $ 1は、括弧の最初のセットでキャプチャされたものです。 $ 2は2番目のセットなどになります。

4
Kyle Brandt

Shellに加えてbashとして質問にタグを付けたため、grepの横に別の解決策があります:

Bashには、Perlと同様に、=~演算子を使用して、バージョン3.0以降に独自の正規表現エンジンがあります。

今、次のコードが与えられた:

#!/bin/bash
DATA="test <Lane>8</Lane>"

if [[ "$DATA" =~ \<Lane\>([[:digit:]]+)\<\/Lane\> ]]; then
        echo $BASH_REMATCH
        echo ${BASH_REMATCH[1]}
fi
  • すべての拡張機能を取得するには、bashではなくshとして呼び出す必要があることに注意してください。
  • $BASH_REMATCHは、正規表現全体と一致する文字列全体を提供するため、<Lane>8</Lane>
  • ${BASH_REMATCH[1]}は、1番目のグループに一致する部分を提供するため、8のみ
4
DrYak

ファイルに以下が含まれていると仮定します。

_$ cat file
Text-here>xyz</more text
_

また、_>_と_</_の間の文字が必要な場合は、次のいずれかを使用できます。

grepgrep -oP '.*\K(?<=>)\w+(?=<\/)' file
sedsed -nE 's:^.*>(\w+)</.*$:\1:p' file
awkawk '{print(gensub("^.*>(\\w+)</.*$","\\1","g"))}' file
PerlPerl -nle 'print $1 if />(\w+)<\//' file

すべて文字列「xyz」を出力します。

この行の数字をキャプチャしたい場合:

_$ cat file
Text-<here>1234</text>-ends
_

grepgrep -oP '.*\K(?<=>)[0-9]+(?=<\/)' file
sedsed -E 's:^.*>([0-9]+)</.*$:\1:' file
awkawk '{print(gensub(".*>([0-9]+)</.*","\\1","g"))}' file
PerlPerl -nle 'print $1 if />([0-9]+)<\//' file

2
Arrow

これはあなたが要求していることを達成しますが、あなたが本当に望んでいることだとは思いません。正規表現の前に.*を置いて、マッチの前に何でも食べますが、これは貪欲な操作であるため、これは文字列の最後から2番目の\w文字にのみ一致します。

括弧と+をエスケープする必要があることに注意してください。

sed 's/.*\(\w\).\+/\1/' myfile.txt
0
Chad Huneycutt