bash: come utilizzare più manipolazioni di stringhe (espansione dei parametri) in un unico passaggio?
Ho string=substr1-substr2-substr3.substr4
dove le sottostringhe sono di lunghezza variabile. Voglio estrarre substr3
da string
e sto pensando di farlo utilizzando le ${string##pattern}
e ${string%pattern}
espansioni manipolazione delle stringhe. Utilizzando questo approccio, è chiaro che devo eseguire ${string##*-}
ed eseguire ${string%.*}
l'espansione risultante, o viceversa. Le mie domande sono:
- è questa la scelta migliore?
- Se sì, come posso eseguire entrambi in un unico passaggio? Quando provo a fare qualcosa di simile
${string##*-${string%.*}}
o${string%.*${string##*-}}
ricevo semplicemente l'intera stringa. Mi rendo conto che potrei sempre fare l'estrazione in due passaggi assegnando una variabile intermedia al risultato del primo passaggio e poi manipolandolo; ma voglio farlo in un solo passaggio. Come posso procedere?
TIA!
Risposte
Dato
string=substr1-substr2-substr3.substr4
${string%.*}
è
substr1-substr2-substr3
così ${string##*-${string%.*}}
è
${string##*-substr1-substr2-substr3}
che significa rimuovere dall'inizio di string
, tutto fino ae incluso -substr1-substr2-substr3
. Ma non esiste una sottostringa di questo tipo string
, poiché non c'è un trattino davanti substr1
, quindi ottieni la stringa originale.
Quello che probabilmente vuoi è
string=substr1-substr2-substr3.substr4
result="${string%.*}" result="${result##*-}"
che porta al result
contenimento substr3
.
In Zsh, potresti farlo in un unico passaggio:, ma non funziona in Bash.result=${${string%.*}##*-}
In Bash, sei limitato all'uso di espansioni sul lato destro di #
o %
, e questo non ti aiuta qui poiché devi rimuovere parti sia dall'inizio che dalla fine della stringa.
In alternativa, se $string
non contiene caratteri di nuova riga, puoi usare
IFS=.- read -r a b c d <<< "$string"
e leggere substr3
da c
.
In tal caso, a seconda della shell e della dimensione della stringa, il contenuto di $string
verrà memorizzato in un file temporaneo o alimentato attraverso una pipe che read
leggerà la prima riga e la dividerà in base a $IFS
.