Unterstützt Bash Rückverweise bei der Parametererweiterung?

Unterstützt Bash Rückverweise bei der Parametererweiterung?

Ich habe eine Variable namens , die eine Zeichenfolge , usw. descrenthalten kann. Ich möchte den , -Teil aus der Zeichenfolge erhalten. Im Moment verwende ich dafür. Gibt es eine bessere Möglichkeit, dies zu tun? Ist dies auch mit Parametererweiterung möglich?Blah: -> r1-ae0-2 / [123]-> s7-Gi0-0-1:1-US / Foo-> r1-ae0-2-> s7-Gi0-0-1:1-USdescr=$(grep -oP '\->\s*\S+' <<< "$descr"

Antwort1

ksh93und zshverfügen über Rückverweise (oder genauer 1 , Verweise auf Erfassungsgruppen im Ersetzungs-)Unterstützung innerhalb von ${var/pattern/replacement}, nicht innerhalb von 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

( mkshAuf der Manpage wird auch erwähnt, dass zukünftige Versionen dies ${KSH_MATCH[1]}für die erste Erfassungsgruppe unterstützen werden. Stand 25.04.2017 noch nicht verfügbar).

Mit können Sie jedoch Folgendes bashtun:

$ [[ $var =~ -\>[[:space:]]*[^[:space:]]+ ]] &&
  printf '%s\n' "${BASH_REMATCH[0]}"
-> r1-ae0-2

Das ist besser, da zuerst geprüft wird, ob das Muster gefunden wird.

Wenn die regulären Ausdrücke Ihres Systems \s/ unterstützen \S, können Sie auch Folgendes tun:

re='->\s*\S+'
[[ $var =~ $re ]]

Mit zshkönnen Sie die volle Leistung von PCREs nutzen mit:

$ set -o rematchpcre
$ [[ $var =~ '->\s*\S+' ]] && printf '%s\n' $MATCH
-> r1-ae0-2

Mit zsh -o extendedglobsiehe auch:

$ printf '%s\n' ${(SM)var##-\>[[:space:]]#[^[:space:]]##}
-> r1-ae0-2

Tragbar:

$ expr " $var" : '.*\(->[[:space:]]*[^[:space:]]\{1,\}\)'
-> r1-ae0-2

Wenn das Muster in der Zeichenfolge mehrfach vorkommt, ist das Verhalten bei allen diesen Lösungen unterschiedlich. Allerdings erhalten Sie bei keiner von ihnen eine durch Zeilenumbrüche getrennte Liste aller Übereinstimmungen wie bei Ihrer GNU-basierten grepLösung.

Dazu müssen Sie die Schleife manuell ausführen. Zum Beispiel mit bash:

re='(->\s*\S+)(.*)'
while [[ $var =~ $re ]]; do
  printf '%s\n' "${BASH_REMATCH[1]}"
  var=${BASH_REMATCH[2]}
done

Mit zshkönnten Sie auf diesen Trick zurückgreifen, um alle Übereinstimmungen in einem Array zu speichern:

set -o extendedglob
matches=() n=0
: ${var//(#m)->[[:space:]]#[^[:space:]]##/${matches[++n]::=$MATCH}}
printf '%s\n' $matches

1 Rückverweise bezeichnen häufiger ein Muster, das auf etwas verweist, das von einer früheren Gruppe abgeglichen wurde. Beispielsweise \(.\)\1gleicht der grundlegende reguläre Ausdruck ein einzelnes Zeichen ab, gefolgt von demselben Zeichen (er gleicht auf aa, nicht auf ab). Das \1ist ein Rückverweis auf diese \(.\)Erfassungsgruppe im gleichen Muster.

ksh93unterstützt Rückverweise in seinen Mustern ( ls -d -- @(?)\1listet beispielsweise die Dateinamen auf, die aus zwei identischen Zeichen bestehen), andere Shells nicht. Standard-BREs und PCREs unterstützen Rückverweise, aber kein Standard-ERE, obwohl einige ERE-Implementierungen es als Erweiterung unterstützen. bash's [[ foo =~ re ]]verwendet EREs.

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

wird nicht übereinstimmen, aber

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

möglich, wenn die EREs des Systems dies unterstützen.

Antwort2

Sie möchten alles bis zum ersten ␣->␣(ohne den „Pfeil“) und nach dem letzten ␣/(einschließlich Leerzeichen und Schrägstrich) löschen.

string="Blah: -> r1-ae0-2 / [123]"
string=${string/*->/->}
string=${string/ \/*}

$stringwird jetzt sein -> r1-ae0-2.

Dieselben beiden Ersetzungen würden zu -> s7-Gi0-0-1:1-US / Foowerden -> s7-Gi0-0-1:1-US.

Antwort3

Eine definitive Antwort darauf ist ohne Kenntnis des genauen Formats nicht möglich.jedenNachricht dauert. Als allgemeine Vorgehensweise können Sie jedoch bestimmte Felder ausdrucken mit cut:

$ cut -d ' ' -f 2 <<< '-> s7-Gi0-0-1:1-US / Foo'
s7-Gi0-0-1:1-US

Oder du kannstjede n-te Spalte drucken mitawk:

$ 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

verwandte Informationen