rimozione di una clausola case: espansione bash in regexp sed: X = 'un \ .b'; Y = ';;' sed -n '/ $ {X} /, / $ {} Y / d'
-
26-09-2019 - |
Domanda
Sto cercando di rimuovere una clausola caso da uno script bash. La clausola può variare, ma avrà sempre backslash come parte della stringa caso-partita.
Cercavo sed ma potrebbe usare awk o perl one-liner all'interno dello script bash.
L'obiettivo della modifica è semplice, assomiglia:
$cat t.sh
case N in
a\.b);
#[..etc., varies]
;;
esac
Sono in esecuzione afoul di espansione variabile di fuga backslash, virgola o entrambi. Se 'eval' io la spoglierò mie fughe backslash. Se non lo faccio, i punti e virgola mi recuperare. Così ho cercato di espansione all'interno della subshell sed. Questo falli l'interprete come ho scritto. Più sfuggire alle punti e virgola non sembra aiuto.
X='a\.b' ; Y=';;'
sed -i '/$(echo ${X} | sed -n 's/\\/\\\\/g')/,/$(echo ${Y} | sed -n s/\;/\\;/g')/d t.sh
E questo:
perl -i.bak -ne 'print unless /${X}/ .. /{$Y}/' t.sh # which empties t.sh
e
eval perl -i.bak -ne \'print unless /${X}/ .. /{$Y}/' t.sh # which does nothing
Soluzione
printf
di Bash ha una caratteristica citando che aiuterà:
X='a\.b'; Y=';;'
sed "/$(printf "%q" "$X")/,/$(printf "%q" "$Y")/d" t.sh
oppure è possibile utilizzare in aggiunta la funzione di assegnazione variabile printf
:
printf -v X "%q" 'a\.b'
printf -v Y "%q" ';;'
sed "/$X/,/$Y/d" t.sh
Si noti l'uso di doppi apici l'argomento del comando sed
. apici singoli impediranno l'espansione delle variabili e sostituzione di comando. Quando non vengono utilizzati quelli, però, di solito è meglio usare le virgolette singole.
Altri suggerimenti
X='a\.b'
Y=';;'
perl -i.bak -ne 'print unless /\Q'$X'/ .. /\Q'$Y'/' t.sh
Questa è giocare con guscio citando, ma funziona abbastanza bene. :)