文字列Blah: -> r1-ae0-2 / [123]
、-> s7-Gi0-0-1:1-US / Foo
などを含むことができるdescr
という名前の変数があります。文字列から-> r1-ae0-2
、-> s7-Gi0-0-1:1-US
の部分を取得したい。現時点では、descr=$(grep -oP '\->\s*\S+' <<< "$descr"
を使用しています。これを行うより良い方法はありますか?パラメータ展開でこれを行うことも可能ですか?
_ksh93
_とzsh
には後方参照があります(より正確には1、置換でのキャプチャグループへの参照)bash
ではなく_${var/pattern/replacement}
_内のサポート。
_ksh93
_:
_$ var='Blah: -> r1-ae0-2 / [123]'
$ printf '%s\n' "${var/*@(->*([[:space:]])+([^[:space:]]))*/\1}"
-> r1-ae0-2
_
zsh
:
_$ var='Blah: -> r1-ae0-2 / [123]'
$ set -o extendedglob
$ printf '%s\n' "${var/(#b)*(->[[:space:]]#[^[:space:]]##)*/$match[1]}"
-> r1-ae0-2
_
(mksh
manページには、将来のバージョンで最初のキャプチャグループの_${KSH_MATCH[1]}
_がサポートされることも記載されています。2017年4月25日現在、まだ使用できません)。
ただし、bash
を使用すると、次のことができます。
_$ [[ $var =~ -\>[[:space:]]*[^[:space:]]+ ]] &&
printf '%s\n' "${BASH_REMATCH[0]}"
-> r1-ae0-2
_
最初にパターンが見つかったことを確認するので、どちらが良いでしょう。
システムの正規表現が_\s
_/_\S
_をサポートしている場合は、次のこともできます。
_re='->\s*\S+'
[[ $var =~ $re ]]
_
zsh
を使用すると、PCREの能力を最大限に引き出すことができます。
_$ set -o rematchpcre
$ [[ $var =~ '->\s*\S+' ]] && printf '%s\n' $MATCH
-> r1-ae0-2
_
_zsh -o extendedglob
_の場合、以下も参照してください。
_$ printf '%s\n' ${(SM)var##-\>[[:space:]]#[^[:space:]]##}
-> r1-ae0-2
_
ポータブル:
_$ expr " $var" : '.*\(->[[:space:]]*[^[:space:]]\{1,\}\)'
-> r1-ae0-2
_
文字列にパターンが複数出現する場合、すべてのソリューションで動作が異なります。ただし、GNU -grep
ベースのソリューションのように、すべての一致を改行で区切ったリストを提供するものはありません。
そのためには、ループを手作業で行う必要があります。たとえば、bash
の場合:
_re='(->\s*\S+)(.*)'
while [[ $var =~ $re ]]; do
printf '%s\n' "${BASH_REMATCH[1]}"
var=${BASH_REMATCH[2]}
done
_
zsh
を使用すると、この種のトリックを使用して、すべての一致を配列に格納できます。
_set -o extendedglob
matches=() n=0
: ${var//(#m)->[[:space:]]#[^[:space:]]##/${matches[++n]::=$MATCH}}
printf '%s\n' $matches
_
1 後方参照は、以前のグループと一致したものを参照するパターンをより一般的に指定します。たとえば、\(.\)\1
基本正規表現は、単一の文字の後にその同じ文字が続くものと一致します(aa
ではなくab
で一致します)。その_\1
_は、同じパターンの\(.\)
キャプチャグループへの後方参照です。
_ksh93
_は、他のシェルではなく、そのパターンで後方参照をサポートします(たとえば、ls -d -- @(?)\1
は2つの同一の文字で構成されるファイル名をリストします)。標準のBREとPCREは後方参照をサポートしていますが、標準のEREはサポートしていませんが、一部のERE実装は拡張としてサポートしています。 bash
の_[[ foo =~ re ]]
_はEREを使用します。
_[[ aa =~ (.)\1 ]]
_
一致しませんが、
_re='(.)\1'; [[ aa =~ $re ]]
_
システムのEREがサポートしている場合があります。
最初の␣->␣
(「矢印」を含まない)まで、および最後の␣/
の後(スペースとスラッシュを含む)までのすべてを削除します。
string="Blah: -> r1-ae0-2 / [123]"
string=${string/*->/->}
string=${string/ \/*}
$string
は-> r1-ae0-2
になります。
同じ2つの置換は、-> s7-Gi0-0-1:1-US / Foo
を-> s7-Gi0-0-1:1-US
に変換します。
everyメッセージが受け取る正確な形式を知らなければ、これに明確に答えることは不可能です。ただし、一般的なアプローチとして、cut
を使用して特定のフィールドを印刷できます。
$ cut -d ' ' -f 2 <<< '-> s7-Gi0-0-1:1-US / Foo'
s7-Gi0-0-1:1-US
または awk
を使用してn列ごとに出力 :
$ awk -F' ' '{ for (i=2;i<=NF;i+=4) print $i }' <<< '-> r1-ae0-2 / [123], -> s7-Gi0-0-1:1-US / Foo'
r1-ae0-2
s7-Gi0-0-1:1-US