web-dev-qa-db-ja.com

ターミナルでRegExを使用して文字列から文字列を抽出します

_first url, second url, third url_のようなstringがあり、単語urlの後のsecondのみを抽出したいOS Xターミナル(最初の出現のみ)。どうすればいいですか?

私のお気に入りのエディターで正規表現/second (url)/を使用し、_$1_を使用して抽出しましたが、ターミナル。

urlは実際のURLであることに注意してください。次の式のいずれかを使用して一致させます。 RLに一致する正規表現

37
fregante
echo 'first url, second url, third url' | sed 's/.*second//'

編集:私は誤解しました。より良い:

echo 'first url, second url, third url' | sed 's/.*second \([^ ]*\).*/\1/'

または:

echo 'first url, second url, third url' | Perl -nle 'm/second ([^ ]*)/; print $1'
54
Sjoerd

別のプロセス(上記の「sed」や「Perl」など)へのパイピングは、特にこの操作を複数回実行する必要がある場合、非常に高価になる可能性があります。 Bashは正規表現をサポートします:

[["string" =〜regex]]

$1$2などを使用してお気に入りのエディターで一致を抽出する方法と同様に、Bashは$BASH_REMATCH配列にすべての一致を入力します。

あなたの特定の例では:

str="first usr1, second url2, third url3"
if [[ $str =~ (second )([^,]*) ]]; then echo "match: '${BASH_REMATCH[2]}'"; else echo "no match found"; fi

出力:

match: 'url2'

具体的には、=~extended正規表現をサポートします POSIXで定義 、ただしプラットフォーム固有の拡張機能(範囲が異なり、互換性がない場合があります)。
Linuxプラットフォーム(GNUユーザーランド)では、man grepを参照してください。 macOS/BSDプラットフォームでは、man re_formatを参照してください。

13

他の回答では、目的のURLの後にすべてが残っています。そこで、次の解決策を提案します。

echo 'first url, second url, third url' | sed 's/.*second \(url\)*.*/\1/'

Sedでは、括弧をエスケープして式をグループ化します(POSIX標準)。

7
mhitza

これを試している間、おそらく忘れていたのはsed-E引数でした。

sed --helpから:

  -E, -r, --regexp-extended
                 use extended regular expressions in the script
                 (for portability use POSIX -E).

正規表現を大幅に変更する必要はありませんが、.*を追加して、文字列の他の部分を削除するために貪欲に一致させる必要があります。

これは私にとってはうまくいきます:

echo "first url, second url, third url" | sed -E 's/.*second (url).*/\1/'

出力:

url

出力 "url"は実際には文字列の2番目のインスタンスです。ただし、コンマとスペースの間にフォーマットされていることをすでに知っていて、URLでこれらの文字を許可しない場合は、正規表現[^,]*で問題ありません。

オプションで:

echo "first http://test.url/1, second ://test.url/with spaces/2, third ftp://test.url/3" \
     | sed -E 's/.*second ([a-zA-Z]*:\/\/[^,]*).*/\1/'

正しく出力されるもの:

://example.com/with spaces/2
2
Yeti