Bash supporta i riferimenti posteriori nell'espansione dei parametri?


15

Ho una variabile chiamata descrche può contenere una stringa Blah: -> r1-ae0-2 / [123], -> s7-Gi0-0-1:1-US / Fooecc voglio ottenere il -> r1-ae0-2, -> s7-Gi0-0-1:1-USparte dalla stringa. Al momento lo uso descr=$(grep -oP '\->\s*\S+' <<< "$descr"per questo. C'è un modo migliore per farlo? È anche possibile farlo con l'espansione dei parametri?

Risposte:


20

ksh93e zshavere il supporto di back-reference (o più precisamente 1 , riferimenti ai gruppi di acquisizione nella sostituzione) all'interno ${var/pattern/replacement}, no 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

(la mkshpagina man menziona anche che le versioni future lo supporteranno ${KSH_MATCH[1]}per il primo gruppo di acquisizione. Non ancora disponibile dal 25/04/2017).

Tuttavia, con bash, puoi fare:

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

Il che è meglio in quanto controlla che il modello sia trovato per primo.

Se il supporto di regexps del tuo sistema \s/ \S, puoi anche fare:

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

Con zsh, puoi ottenere tutta la potenza dei PCRE con:

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

Con zsh -o extendedglob, vedi anche:

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

portabile:

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

Se ci sono diverse occorrenze del modello nella stringa, il comportamento varierà con tutte quelle soluzioni. Tuttavia, nessuno di loro ti fornirà un elenco separato da una nuova riga di tutte le partite come nella tua GNU-grep soluzione basata su .

Per fare ciò, dovresti fare il loop a mano. Ad esempio, con bash:

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

Con zsh, potresti ricorrere a questo tipo di trucco per memorizzare tutte le partite in un array:

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

1 riferimenti secondari designano più comunemente un modello che fa riferimento a ciò che è stato abbinato a un gruppo precedente. Ad esempio, l' \(.\)\1espressione regolare di base corrisponde a un singolo carattere seguito dallo stesso carattere (corrisponde a attivo aa, non attivo ab). Questo \1è un riferimento a quel \(.\)gruppo di acquisizione nello stesso modello.

ksh93supporta i riferimenti a ritroso nei suoi modelli (ad esempio ls -d -- @(?)\1elencherà i nomi dei file costituiti da due caratteri identici), non altre shell. BRE standard e PCRE supportano riferimenti secondari ma non ERE standard, sebbene alcune implementazioni di ERE lo supportino come estensione. bash's [[ foo =~ re ]]usi ERE.

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

non corrisponderà, ma

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

può se gli ERE del sistema lo supportano.


9

Vuoi eliminare tutto fino al primo ␣->␣(esclusa la "freccia") e dopo l'ultimo ␣/(compresi lo spazio e la barra).

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

$stringsarà ora -> r1-ae0-2.

Le stesse due sostituzioni si trasformerebbero -> s7-Gi0-0-1:1-US / Fooin -> s7-Gi0-0-1:1-US.


3

Rispondere definitivamente a questo è impossibile senza conoscere il formato esatto che prende ogni messaggio. Tuttavia, come approccio generale è possibile stampare determinati campi specifici utilizzando cut:

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

Oppure puoi stampare ogni ennesima colonna usandoawk :

$ 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.