bashはパラメータ拡張時の逆参照をサポートしますか?

bashはパラメータ拡張時の逆参照をサポートしますか?

文字列などを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 ]]

これにより、zshPCREのすべての機能を次のように取得できます。

$ 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

文字列でパターンが複数回発生する場合、これらの解決策はすべて異なる動作をします。しかし、それらのどれも、grepGNUベースのソリューションのように改行で区切られたすべての一致リストを提供するわけではありません。

これを行うには手動で繰り返す必要があります。たとえば、次のようになります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 -- @(?)\12つの同じ文字で構成されるファイル名が一覧表示されますが、他のシェルではサポートされません。逆参照は標準BREとPCREでサポートされていますが、標準EREではサポートされていません。ただし、一部のERE実装ではこれを拡張としてサポートしています。 EREを使用bashしてください[[ foo =~ re ]]

[[ aa =~ (.)\1 ]]

似合わないけど

re='(.)\1'; [[ aa =~ $re ]]

システムのEREがサポートしている場合は可能です。

おすすめ記事