Niedawno miałem problem z pewnym wyrażeniem regularnym w wierszu poleceń i odkryłem, że do dopasowania odwrotnego ukośnika można użyć różnej liczby znaków. Liczba ta zależy od cytowania użytego w wyrażeniu regularnym (brak, pojedyncze cudzysłowy, podwójne cudzysłowy). Zobacz, co mam na myśli, w poniższej sesji bash:
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
To znaczy że:
- bez cudzysłowów, mogę dopasować odwrotny ukośnik z 4-7 rzeczywistymi odwrotnymi ukośnikami
- z podwójnymi cudzysłowami mogę dopasować odwrotny ukośnik z 3-6 rzeczywistymi odwrotnymi ukośnikami
- Z pojedynczymi cudzysłowami mogę dopasować odwrotny ukośnik z 2-3 rzeczywistymi odwrotnymi ukośnikami
Rozumiem, że jeden dodatkowy ukośnik odwrotny jest ignorowany przez powłokę (ze strony podręcznika bash):
„Niecytowany ukośnik odwrotny (\) to znak zmiany znaczenia. Zachowuje on dosłowną wartość następnego następującego po nim znaku”
Nie dotyczy to przykładów z pojedynczymi cudzysłowami, ponieważ w pojedynczych cudzysłowach nie jest wykonywana żadna zmiana znaczenia.
Jeden dodatkowy ukośnik odwrotny jest ignorowany przez polecenie grep („\ c” to tylko „c”, ale jest to to samo co „c”, ponieważ „c” nie ma specjalnego znaczenia w wyrażeniu regularnym).
Wyjaśnia to zachowanie przykładu z pojedynczymi cudzysłowami, ale tak naprawdę nie rozumiem dwóch pozostałych przykładów, szczególnie dlaczego istnieje różnica między nieokreślonymi ciągami cudzysłowów.
Ponownie cytat ze strony podręcznika użytkownika bash:
„Umieszczanie znaków w podwójnych cudzysłowach zachowuje dosłowną wartość wszystkich znaków w cudzysłowach, z wyjątkiem $,`, \ oraz, gdy włączone jest rozszerzanie historii,! ”.
Próbowałem tego samego z GNU awk (np. awk /ab\cd/{print} file
), Z tymi samymi wynikami.
Perl pokazuje jednak różne wyniki (używając np. perl -ne
"/ab\\cd/"\&\&print file
):
- bez cudzysłowów, mogę dopasować odwrotny ukośnik z 4-5 rzeczywistymi odwrotnymi ukośnikami
- z podwójnymi cudzysłowami mogę dopasować odwrotny ukośnik z 3-4 rzeczywistymi odwrotnymi ukośnikami
- Z pojedynczymi cudzysłowami mogę dopasować odwrotny ukośnik z 2 rzeczywistymi odwrotnymi ukośnikami
Czy ktoś może wyjaśnić tę różnicę między ciągami wyrażeń regularnych niekwotowanych i podwójnie znakowanych w wierszu poleceń dla grep i awk? Wyjaśnienie zachowania Perla nie interesuje mnie tak bardzo, ponieważ zazwyczaj nie korzystam z linijek Perla.
printf "\ntest"
wstawi nowy wiersz przed „testem”, nawet jeśli"\n"
powinien być przetłumaczony"n"
przez powłokę, ponieważ zawiera podwójne cudzysłowy ... (więc oczekiwany wynik powinien być, dla "\ ntest", "ntest". Powinniśmy mieć nawyk pisania:printf "\\ntest"
lubprintf '\ntest'
, ale jakoś widzę dużo skryptu polegającego na osobliwości.