Di recente ho avuto problemi con alcuni regex sulla riga di comando e ho scoperto che per abbinare una barra rovesciata, è possibile utilizzare diversi numeri di caratteri. Questo numero dipende dalla quotazione utilizzata per la regex (nessuna, virgolette singole, virgolette doppie). Vedi la seguente sessione bash per cosa intendo:
echo "#ab\\cd" > file
grep -E ab\cd file
grep -E ab\\cd file
grep -E ab\\\cd file
grep -E ab\\\\cd file
#ab\cd
grep -E ab\\\\\cd file
#ab\cd
grep -E ab\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\\cd file
grep -E "ab\cd" file
grep -E "ab\\cd" file
grep -E "ab\\\cd" file
#ab\cd
grep -E "ab\\\\cd" file
#ab\cd
grep -E "ab\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\\cd" file
grep -E 'ab\cd' file
grep -E 'ab\\cd' file
#ab\cd
grep -E 'ab\\\cd' file
#ab\cd
grep -E 'ab\\\\cd' file
Ciò significa che:
- senza virgolette, posso abbinare una barra rovesciata con 4-7 barre rovesciate effettive
- con le virgolette doppie, posso abbinare una barra rovesciata con 3-6 barre rovesciate effettive
- Con virgolette singole, posso abbinare una barra rovesciata con 2-3 barre rovesciate effettive
Capisco che una barra rovesciata in più viene ignorata dalla shell (dalla pagina man di bash):
"Una barra rovesciata non quotata (\) è il carattere di escape. Conserva il valore letterale del carattere successivo che segue"
Questo non si applica agli esempi con virgolette singole, poiché non viene eseguita alcuna escape tra virgolette singole.
E una barra rovesciata aggiuntiva viene ignorata dal comando grep ("\ c" è solo "c" evaso, ma questo è lo stesso di "c", perché "c" non ha un significato speciale in una regex).
Questo spiega il comportamento dell'esempio con virgolette singole, ma in realtà non capisco gli altri due esempi, soprattutto perché c'è una differenza tra stringhe non qouted e doppie tra virgolette.
Ancora una volta, una citazione dalla pagina man di bash:
"Racchiudere i caratteri tra virgolette doppie conserva il valore letterale di tutti i caratteri tra virgolette, ad eccezione di $,`, \ e, quando l'espansione della cronologia è abilitata,!. "
Ho provato lo stesso con GNU awk (ad esempio awk /ab\cd/{print} file
), con gli stessi risultati.
Perl, tuttavia, mostra risultati diversi (usando ad esempio perl -ne
"/ab\\cd/"\&\&print file
):
- senza virgolette, posso abbinare una barra rovesciata con 4-5 barre rovesciate effettive
- con le virgolette doppie, posso abbinare una barra rovesciata con 3-4 barre rovesciate effettive
- Con virgolette singole, posso associare una barra rovesciata a 2 barre rovesciate effettive
Qualcuno può spiegare quella differenza tra stringhe regex non quotate e double qouted sulla riga di comando per grep e awk? Non sono così interessato a una spiegazione del comportamento di Perl, dal momento che di solito non uso le battute Perl.
printf "\ntest"
inserirà una nuova riga prima di "test", anche se"\n"
avrebbe dovuto essere tradotto"n"
dalla shell in quanto è racchiuso tra virgolette ... (quindi il risultato atteso dovrebbe essere, per "\ ntest", "ntest". Dovremmo prendere l'abitudine di scrivere:printf "\\ntest"
oprintf '\ntest'
, ma in qualche modo vedo molte sceneggiature che fanno affidamento sulla stranezza.