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.
źródło
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.Ten link opisuje Bash Quotes and Escaping
Twoje pytanie dotyczy trzech pierwszych części.
Poniżej znajduje się wykres, w jaki sposób ciągi
bash
te są przekazywanegrep
i jakgrep
dalej interpretuje je wewnętrznie.Spójrzmy na
echo "#ab\\cd" > file
.W słabej cytowane ( „”)
"#ab\\cd"
The\\
jest uciec\
, które wprowadza się dofile
postaci pojedynczego dosłownym\
. Więcfile
zawieraab\cd
Teraz do twoich poleceń: Poniższa tabela może pomóc zobaczyć, co faktycznie dzieje się z każdym połączeniem.
*
Pokazuje te, które odpowiadają zawartości plików. Tak naprawdę to tylko kwestia zastosowania reguł ucieczki basha, tak jak na stronie internetowej, ze szczególnym uwzględnieniem odpowiedzi Daniela Kullmanna, w której odnosi się do zachowania ucieczki w sytuacji słabego cytowania .źródło