Gần đây tôi đã gặp sự cố với một số biểu thức chính trên dòng lệnh và thấy rằng để khớp với dấu gạch chéo ngược, có thể sử dụng số lượng ký tự khác nhau. Con số này phụ thuộc vào trích dẫn được sử dụng cho regex (không có, dấu ngoặc đơn, dấu ngoặc kép). Xem phiên bash sau đây để biết ý tôi là gì:
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
Điều này có nghĩa rằng:
- không có dấu ngoặc kép, tôi có thể kết hợp dấu gạch chéo ngược với 4-7 dấu gạch chéo ngược thực tế
- với dấu ngoặc kép, tôi có thể kết hợp dấu gạch chéo ngược với 3-6 dấu gạch chéo ngược thực tế
- Với dấu ngoặc đơn, tôi có thể kết hợp dấu gạch chéo ngược với 2-3 dấu gạch chéo ngược thực tế
Tôi hiểu rằng một dấu gạch chéo ngược bổ sung bị bỏ qua bởi trình bao (từ trang bash man):
"Dấu gạch chéo ngược không được trích dẫn (\) là ký tự thoát. Nó giữ nguyên giá trị theo nghĩa đen của ký tự tiếp theo sau"
Điều này không áp dụng cho các ví dụ trích dẫn đơn, bởi vì không có lối thoát nào được thực hiện trong dấu ngoặc đơn.
Và một dấu gạch chéo ngược bổ sung bị bỏ qua bởi lệnh grep ("\ c" chỉ là "c" đã thoát, nhưng điều này cũng giống như "c", vì "c" không có ý nghĩa đặc biệt trong regex).
Điều này giải thích hành vi của ví dụ với các trích dẫn đơn, nhưng tôi không thực sự hiểu hai ví dụ khác, đặc biệt là tại sao có sự khác biệt giữa các chuỗi không trích dẫn.
Một lần nữa, một trích dẫn từ trang bash man:
"Việc bao gồm các ký tự trong dấu ngoặc kép sẽ giữ giá trị bằng chữ của tất cả các ký tự trong dấu ngoặc kép, ngoại trừ $,`, \, và, khi mở rộng lịch sử được bật,!. "
Tôi đã thử tương tự với GNU awk (ví dụ awk /ab\cd/{print} file
), với kết quả tương tự.
Tuy nhiên, Perl hiển thị các kết quả khác nhau (sử dụng ví dụ perl -ne
"/ab\\cd/"\&\&print file
):
- không có dấu ngoặc kép, tôi có thể kết hợp dấu gạch chéo ngược với 4-5 dấu gạch chéo ngược thực tế
- với dấu ngoặc kép, tôi có thể kết hợp dấu gạch chéo ngược với 3-4 dấu gạch chéo ngược thực tế
- Với dấu ngoặc đơn, tôi có thể khớp dấu gạch chéo ngược với 2 dấu gạch chéo ngược thực tế
Bất cứ ai cũng có thể giải thích sự khác biệt giữa các chuỗi regex không trích dẫn và hai lần trên dòng lệnh cho grep và awk? Tôi không quan tâm đến lời giải thích về hành vi của Perl, vì tôi thường không sử dụng Perl một lớp.
printf "\ntest"
sẽ chèn một dòng mới trước khi "kiểm tra", mặc dù"\n"
đã được dịch sang"n"
shell vì đó là dấu ngoặc kép của whithin ... (vì vậy kết quả mong đợi sẽ là, cho "\ ntest", "ntest". Chúng ta nên tập thói quen viết:printf "\\ntest"
hoặcprintf '\ntest'
, nhưng bằng cách nào đó tôi thấy rất nhiều kịch bản dựa vào sự kỳ quặc thay vào đó.