Lệnh cut
có một tùy chọn -c
để làm việc trên các ký tự, thay vì byte với tùy chọn -b
. Nhưng điều đó dường như không hoạt động, tại en_US.UTF-8
địa phương:
Byte thứ hai cho ký tự ASCII thứ hai (được mã hóa giống như trong UTF-8):
$ printf 'ABC' | cut -b 2
B
nhưng không đưa ra lần thứ hai trong ba ký tự không phải ASCII của Hy Lạp trong ngôn ngữ UTF-8:
$ printf 'αβγ' | cut -b 2
�
Không sao đâu - đó là byte thứ hai .
Vì vậy, chúng tôi nhìn vào nhân vật thứ hai thay thế:
$ printf 'αβγ' | cut -c 2
�
Điều đó có vẻ bị hỏng.
Với một số thử nghiệm, hóa ra phạm vi 3-4
hiển thị ký tự thứ hai:
$ printf 'αβγ' | cut -c 3-4
β
Nhưng điều đó cũng giống như các byte 3 đến 4:
$ printf 'αβγ' | cut -b 3-4
β
Nên -c
không nhiều hơn -b
UTF-8.
Tôi hy vọng thiết lập ngôn ngữ không phù hợp với UTF-8, nhưng so sánh, wc
hoạt động như mong đợi;
Nó thường được sử dụng để đếm byte, với tùy chọn -c
( --bytes
).
(Lưu ý các tên tùy chọn khó hiểu.)
$ printf 'αβγ' | wc -c
6
Nhưng nó cũng có thể đếm các ký tự với tùy chọn -m
( --chars
), chỉ hoạt động:
$ printf 'αβγ' | wc -m
3
Vì vậy, cấu hình của tôi có vẻ ổn - nhưng có gì đó đặc biệt cut
.
Có lẽ nó không hỗ trợ UTF-8 chút nào? Nhưng nó dường như hỗ trợ các ký tự nhiều byte, nếu không, nó sẽ không cần hỗ trợ -b
và -c
.
Vì vậy những gì là sai? Và tại sao?
Thiết lập ngôn ngữ có vẻ phù hợp với utf8, theo như tôi có thể nói:
$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE=en_US.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
Đầu vào, byte theo byte:
$ printf 'αβγ' | hd
00000000 ce b1 ce b2 ce b3 |......|
00000006
-c
là sử dụng cùng một mã như-b
. Bạn đã xem mã nguồn chưa? Có lẽ bạn có thể tìm thấy một gợi ý những gì-c
thực sự có nghĩa là cho.