文字列などをdescr
含めることができる変数がありますBlah: -> r1-ae0-2 / [123]
。-> s7-Gi0-0-1:1-US / Foo
私は文字列から部分を取得したいと思います-> r1-ae0-2
。-> s7-Gi0-0-1:1-US
現在私はdescr=$(grep -oP '\->\s*\S+' <<< "$descr"
これを使用しています。もっと良い方法がありますか?パラメータ拡張でこれを行うことはできますか?
答え1
ksh93
代わりに、zsh
逆参照(より正確には代替項目のキャプチャグループへの参照)の内部サポートがあります。${var/pattern/replacement}
bash
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
マニュアルページでは、今後のバージョンが最初の${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
文字列でパターンが複数回発生する場合、これらの解決策はすべて異なる動作をします。しかし、それらのどれも、grep
GNUベースのソリューションのように改行で区切られたすべての一致リストを提供するわけではありません。
これを行うには手動で繰り返す必要があります。たとえば、次のようになります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
表現は、単一の文字とそれに続く同じ文字を一致させます(onaa
ではなくonと一致しますab
)。これは、\1
同じパターンのキャプチャグループの逆参照です。\(.\)
ksh93
このモードは逆参照をサポートしますが、たとえばls -d -- @(?)\1
2つの同じ文字で構成されるファイル名が一覧表示されますが、他のシェルではサポートされません。逆参照は標準BREとPCREでサポートされていますが、標準EREではサポートされていません。ただし、一部のERE実装ではこれを拡張としてサポートしています。 EREを使用bash
してください[[ foo =~ re ]]
。
[[ aa =~ (.)\1 ]]
似合わないけど
re='(.)\1'; [[ aa =~ $re ]]
システムのEREがサポートしている場合は可能です。
答え2
␣->␣
最初の項目(「矢印」を除く)と最後の項目(スペースとスラッシュを含む)以降のすべての␣/
項目を削除しようとしています。
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
。
答え3
正確な形式がわからないと、この質問にはっきりと答えることはできません。すべてメッセージが必要です。ただし、一般的な方法では、以下を使用して特定のフィールドを印刷できますcut
。
$ cut -d ' ' -f 2 <<< '-> s7-Gi0-0-1:1-US / Foo'
s7-Gi0-0-1:1-US
それともできます。n番目の列ごとに印刷に使用awk
:
$ 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