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


13

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

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

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

行全体に一致するため、grepを使用できるとは思わないでください。

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

回答:


11

2つのこと:

  • @Roryで述べられている-oように、オプションが必要なので、(行全体ではなく)一致のみが出力されます
  • さらに、Look先Look behind-Pなどの便利な要素を含むPerlの正規表現を使用するオプションが必要です。 (?= ) (?<= )

parensis内の部分のみを一致させたい場合:

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

ファイルにスティングが含まれている場合/(a)5667/、grepは「a」を出力します。理由は次のとおりです。

  • /(によって発見されます\/\(が、それらは後読みされ (?<= )ているため、報告されません
  • aマッチングされ\w、したがって、(のために印刷されています-o
  • )5667/b <が見つかりました\).+\/が、先読みされ (?= )ているため報告されません

17

-oオプションを使用しますgrep

例えば:

$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar

4
深い悲しみ...私はそれsedを行うために後方参照で何回取り組んだか考えていますか?
Insyte

9
grep / egrepのoオプションは、彼が要求したように()にあるものだけでなく、正規表現全体に一致したもののみを返します。
カイルブラント

1
しかし、それはとにかく知っておくのはとても良いことです:
カイルブラント

2
@KyleBrandt:1つの部分(例:括弧)のみに一致させるには、残りを先読みまたは後ろ読みでマークすることができます:(?<=)および(?=)
DrYak

6
    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

4

かっこ内のものだけが必要な場合は、サブマッチのキャプチャをサポートするもの(名前付きまたは番号付きキャプチャグループ)が必要です。grepやegrepでこれができるとは思わない、perlやsedでできる。たとえば、perlの場合:

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

/adsdds      /

あなたがやる:

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

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


かっこ内にあるものと一致させようとしていました。perlまたはphpスクリプトに渡すように思えるでしょう。
アレックスL

4

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

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

今、次のコードを与えられます:

#!/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

親愛なる@DrYak、ここで正規表現を使用してXMLを解析していないことを願っています。:)
joonas.fi

さらに悪いことです。SANSparallelの高速大規模アライメントソフトウェア>によって出力された、XMLとFASTAデータ(両方ともまったく異なる目的にシンボルを使用)の恐ろしい組み合わせを解析しています。もちろん、どちらの形式もエスケープせずにインターレースで吐き出されます。したがって、これに標準のXMLライブラリをスローすることは不可能です。また、コードのこの時点でBash正規表現を使用しているのは、2、3のデータを抽出するだけで済み、この混乱のために専用のパーサーを作成するよりも2正規表現の方がはるかに優れているからです。#LifeInBioinformatics
DrYak

つまり、XMLタンゴ全体を踊るよりも、正規表現を使用して1つの数字を抽出する方が簡単な点がある
-DrYak

ハァッ!:)
joonas.fi

2

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

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

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

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

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

この行の数字をキャプチャする場合:

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

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


私にとって重要なのは、\ dがsedで動作しないことを認識することでした。そこで[0-9] +を使用する理由があります。:)
user27432

@ user27423それはしませんが、POSIX文字クラス(痛みを伴う読書快適な読書は)実行しますecho 'Text-<here>1234</text>-ends' | sed -E 's|.*>([[:digit:]]+)<.*|\1|'。いくつかのケース(例えばで[0-9][[:digit:]])、彼らは他の人に私が(例えば、彼らがそう考えて、ないのヘルプ読みやすさを行う[ \t\n\r\f\v][:space:])。
サミュエルハーマー

0

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

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

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