Tại sao bash thay thế biến đổi toàn cầu hoạt động ở mức byte?


7

Tôi nghĩ rằng sự thay thế và bash biến bash hoạt động ở độ phân giải ký tự , vì vậy tôi khá ngạc nhiên khi thấy nó hoạt động ở mức byte .
Mọi thứ trong tôi localeen_AU.UTF-8

Khi không có gì phù hợp và mẫu cho phép từ 0 đến nhiều, sự thay thế xảy ra ở mức byte , như được thấy trong các thay thế tiếp theo. Tôi đã mong nó sẽ chuyển sang nhân vật tiếp theo , nhưng nó không ...

Có lẽ đây chỉ là một mô hình trường hợp rìa, hoặc tôi đang thiếu một cái gì đó rõ ràng, nhưng tôi tự hỏi điều gì đang xảy ra ở đây, và tôi có thể mong đợi hành vi này ở nơi nào khác ngoài mô hình cụ thể này không?

Đây là kịch bản (bắt đầu như một nỗ lực để tách một chuỗi thành các ký tự).
Tôi hy vọng rằng bài kiểm tra cuối cùng, với ký tự , sẽ chỉ có một khoảng trắng duy nhất ở trước , nhưng thay vào đó, 3 byte UTF-8 của ký tự được đặt trước một khoảng trắng. Điều này dẫn đến đầu ra UTF-8 không hợp lệ.

shopt -s extglob
for str in  $'\t' "ab"   ;do
    printf -- '%s' "${str//*($'\x01')/ }" |xxd
done

Đầu ra:

0000000: 2009                                      .
0000000: 2061 2062                                 a b
0000000: 20e0 20a4 20b3                            . . .

bạn đang sử dụng phiên bản bash nào?
bsd

Tôi yêu cầu bởi vì có 67 tài liệu tham khảo về 'multibyte' trong nhật ký thay đổi bash . Đặc biệt, bbbb.
bsd

Tôi đang sử dụng GNU bash 4.1.5 ... cụ thể hơn: GNU bash, phiên bản 4.1.5 (1) -release (i486-pc-linux-gnu) trên Ubuntu 10.04.4 LTS sáng suốt ... Linux 2.6.32 -38-generic-pae GNU / Linux
Peter.O

Câu trả lời:


4

Câu trả lời ngắn cho câu hỏi của bạn là * (danh sách mẫu) sẽ khớp với 0 hoặc nhiều lần xuất hiện của các mẫu đã cho. Không có phiên bản nào của ký tự Unicode 0001 giữa mỗi byte đầu vào. Vì vậy, hoạt động thay thế thay thế từng trường hợp không bằng một không gian duy nhất.

Có lẽ bạn muốn làm điều này:

$ for str in  $'\t' "ab"   ; do  
    printf -- '%s' "${str//+($'\x01')/ }" |xxd
  done)
0000000: 09                                       .
0000000: 6162                                     ab
0000000: e0a4 b3                                  ...

Nhưng câu trả lời dài hơn là trong mọi trường hợp, tên đường dẫn không phải là văn bản. Ít nhất, chúng không liên quan đến hệ điều hành (giống Unix). Chúng là các chuỗi byte. Vấn đề là những thứ như thế này là tầm thường để làm:

$ LC_ALL=latin1
$ mkdir 'áñ' && cd 'áñ'
$ LC_ALL=ga_IE.iso885915@euro
$ mkdir '€25' && cd '€25'
$ LC_ALL=zh_TW
$ pwd
# ... what should the output be?  And what about the output of:
$ /bin/pwd

Mỗi địa phương đó bao gồm các nhân vật không tồn tại trong những địa phương khác. Vấn đề này ảnh hưởng đến những thứ như định vị -rfind -regex nữa; đối số của định vị -r là một biểu thức chính quy, do đó phải bao gồm hỗ trợ cho những thứ như các lớp ký tự; nhưng bạn không biết sử dụng ngôn ngữ nào để xác định các lớp ký tự cho các ký tự trong tên đường dẫn hoặc ngay cả khi có một ngôn ngữ có thể sử dụng duy nhất có thể được sử dụng để thể hiện tất cả các đường dẫn trên hệ thống.


Điều này có nghĩa là ${str//@($'\xB3')/w}chỉ có thể thay thế byte (UTF-8) cuối cùng của (\ xB3) bằng chuỗi w (\ x77) và đúng như vậy! Ngoài ra, ${str//*($'\xB3')/w}nên dẫn đến 77e0 77a4 77, và nó làm! .. Cảm ơn James. Vì vậy, điều này có nghĩa là trong câu trả lời, nó nên đọc Không có trường hợp nào của ký tự Unicode 0001 giữa mỗi byte đầu vào (không phải ký tự) .
Peter.O
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.