Tại sao các chữ in hoa được bao gồm trong một loạt các chữ cái viết thường trong regex awk?


7
$ echo ABC | awk '$0 ~ /^[a-b]/'
ABC
$ echo ABC | awk '$0 ~ /^[a-a]/'
$ echo ABC | awk '$0 ~ /^a/'
$ 

Bạn thấy đấy. /[a-b]/chụp A, nhưng /[a-a]/hoặc /a/không. Tại sao?


1
Xem LC_COLLATE có nên ảnh hưởng đến phạm vi ký tự không? để biết thêm thông tin (chưa được giải quyết) về chủ đề này.
Caleb

Điều này dường như không chỉ là một vấn đề LC_COLLATE đơn giản (?), Bởi vì sử dụng một số giá trị không phải C cho LC_COLLATE tạo ra các kết quả khác nhau, tùy thuộc vào tiện ích nào được sử dụng. ví dụ. 'sed' và 'grep' cung cấp các kết quả khác nhau cho 'awk' khi sử dụng LC_COLLATE = en_AU.UTF-8 hoặc en_US.UTF-8 ... sed và grep quản lý để giải quyết vấn đề trường hợp và chỉ in chữ thường ( sử dụng các giá trị tương tự như trên)
Peter.O

Ít nhất là trong gawk (GNU Awk), điều này đã được sửa ([az] chỉ khớp với các chữ cái viết thường) kể từ phiên bản 4.0: gnu.org/software/gawk/manual/html_node/Ranges-and-Locales.html
Piotr Jurkiewicz

Câu trả lời:


6

Đó là một vấn đề "địa phương", tôi nghĩ vậy.

Ở địa phương của tôi, it_IT, đoạn mã sau

if [[ a < A ]]; then
  echo "a < A"
elif [[ a > A ]]; then
  echo "a > A"
else
  echo "a = A"
fi

if [[ b < A ]]; then
  echo "b < A"
elif [[ b > A ]]; then
  echo "b > A"
else
  echo "b = A"
fi

trình diễn

a < A
b > A

vì vậy đó Alà (đáng ngạc nhiên) giữa ab, trong phạm vi.

Hãy thử thực hiện

echo ABC | LC_COLLATE=C awk '$0 ~ /^[a-b]/'

Biên tập

lệnh sau đây cho thấy thứ tự đối chiếu trong miền địa phương của bạn:

echo $(LC_COLLATE=C printf '%s\n' {A..z} | sort)

đầu ra trên máy của tôi là

` ^ _ [ ] a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z

(không thể hiểu từ trang hướng dẫn của bash nếu các biểu thức trình tự được mở rộng theo thứ tự đối chiếu cục bộ hay không; có vẻ như không).


+1, nhưng bạn chỉ cần LC_COLLATE, không phải LC_ALL, cho trường hợp cụ thể này.
mattdm

@mattdm: bạn nói đúng, tôi lười biếng
enzotib

@enzotib: Tôi đang bối rối ... Ý tưởng này dường như có nghĩa là mỗi lần tôi muốn đặt một phạm vi / [ax] /, tôi phải sử dụng LC_COLLATE .... Điều gì trên trái đất có một chuỗi đối chiếu phải làm để xác định cái gì là Chữ hoa và chữ thường? ... Tôi không thể thấy trình tự Collating quy định thế nào là chữ hoa và cái gì không ... Tôi tiếp tục vật lộn với những vấn đề địa phương này, và đang dần tiến lên, nhưng cái này khiến tôi bối rối.
Peter.O

@fred: thường xuyên, khi sử dụng sort, joinhoặc tương tự, tôi bắt đầu kịch bản của tôi với export LC_COLLATE=C. Bây giờ tôi phải bắt đầu bằng cách này cũng sử dụng các tập lệnh bằng cách sử dụng awk:)
enzotib

2
Thứ tự eval thứ tự không quan trọng trong trường hợp này vì bạn sắp xếp sau khi chuỗi được tạo. Tuy nhiên, ví dụ của bạn sẽ hoạt động chính xác hơn với LC_COLLATE bên cạnh sắp xếp: "echo $ (printf '% s \ n' {A..z} | LC_COLLATE = 'C' sort)" ... sẽ tương phản chính xác với mặc định trường hợp "echo $ (printf '% s \ n' {A..z} | LC_COLLATE = '' sort)". Cú pháp ban đầu ở trên không bao giờ thực sự áp dụng LC_COLLATE được sửa đổi cục bộ cho lệnh sắp xếp [tất nhiên, tất cả các cược sẽ bị tắt nếu LC_ALL được đặt ở đâu đó ...]
MartyMacGyver
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.