Tại sao dấu tách đơn vị (ASCII 31) không nhìn thấy trong đầu ra đầu cuối?


17

Ký tự phân cách đơn vị ASCII (ASCII 31, bát phân 37), hiển thị trong Vim là a ^_. Nhưng nếu tôi in cùng một tệp vào thiết bị đầu cuối, ký tự sẽ không nhìn thấy được. Điều này khiến các trường trên một dòng bị kẹt lại với nhau:

# In Vim and less:

first field^_second field^_last field

# cat the same file to terminal:
cat delim.txt
first fieldsecond fieldlast field

# print 2nd field with awk 
cat delim.txt | awk 'BEGIN {FS = "\037"} {print $2}'
second field

Tôi cho rằng tôi có thể làm cho dấu phân cách đơn vị hiển thị với cat -v:

cat -v delim.txt
first field^_second field^_last field

Nhưng điều này khá cồng kềnh. Tại sao dấu phân cách đơn vị không có biểu thị rõ ràng khi được in ra thiết bị xuất chuẩn trong vỏ Bash? Tôi thậm chí không thể sao chép và dán đầu ra vỏ chính xác; dải phân cách đơn vị bị mất trong quá trình.


Không phải tất cả các ký tự đều có thể in được, dấu phân cách đơn vị là một trong số này. Một số biên tập viên sẽ hiển thị nó theo một cách nào đó để có thể chỉnh sửa. Bạn cần dịch nó thành một chuỗi các ký tự có thể in và có thể là một phông chữ / màu khác nhau, để giảm sự mơ hồ.
ctrl-alt-delor

3
Các mã ASCII dưới 31 và 127, nhằm mục đích khiến thiết bị đầu cuối hoặc thiết bị làm điều gì đó (do đó tại sao chúng được gọi là mã điều khiển) hoặc đại diện cho thứ gì đó trong giao thức (như EOT hoặc SOH), trái ngược với việc hiển thị thứ gì đó. Nó nghe thấy khi các thiết bị đầu cuối là thiết bị giống như máy đánh chữ và những thứ như nói với một loại điện thoại để trả lại xe là cần thiết. Người chỉnh sửa có thể chọn hiển thị chúng bằng cách sử dụng ký hiệu "^" vì bạn đang chỉnh sửa thứ gì đó và không muốn thiết bị đầu cuối thực sự làm những gì mà mã kiểm soát đang yêu cầu.
LawrenceC

1
@LawrenceC: Mã 127 thực sự có ý định làm cho thiết bị đầu cuối không làm gì cả , Nếu một người đấm một cuộn băng và mắc lỗi, người ta sẽ nhấn một nút để sao lưu băng từ một khoảng trống và nhấn "rub-out", để đấm tất cả tám lỗ. Khi người đọc bắt gặp nhân vật bị đục lỗ toàn bộ, nó sẽ gửi nó qua dây nhưng người nhận chỉ có thể bỏ qua.
supercat

Câu trả lời:


19

Ký tự dấu phân cách đơn vị ( US), còn được gọi là IS1, nằm trong cntrllớp ký tự và không thuộc printlớp ký tự. Đó là một ký tự điều khiển nhằm tổ chức văn bản thành các nhóm, cho các chương trình được thiết kế để sử dụng thông tin đó . Nói chung, các ký tự không in được có thể sẽ được diễn giải và hiển thị khác nhau trong các chương trình hoặc môi trường khác nhau.

Lý do bạn thấy nó được thể hiện như ^_trong Vim là vì Vim là một trình soạn thảo tương tác. Nó có thể tự do kết xuất các ký tự không in được theo ý muốn, miễn là ký tự nhị phân chính xác được ghi vào đĩa.

Bạn không thể có hành vi tương tự trong trình bao vì các chương trình shell Unix được viết để hoạt động và truyền văn bản đơn giản cho nhau. Khi bạn catmột tệp, văn bản được ghi vào thiết bị đầu cuối phải là những gì thực sự có trong tệp.

Vì vậy, để nó cho thiết bị đầu cuối để giải thích các nhân vật. Và nó chỉ ra rằng một số trình giả lập thiết bị đầu cuối làm cho USnhân vật khác với những người khác. Trong gnome-terminal(hoặc bất kỳ vtethiết bị đầu cuối nào), ký tự sẽ được hiển thị dưới dạng hộp chứa mã hex 001F. Trong xtermhoặc rxvt, nhân vật thực sự là vô hình.


Vâng, tôi sẽ không nói UShoàn toàn vô hình. Khi tôi chèn ký tự đó vào một thiết bị đầu cuối với Ctrl+/(được xác nhận qua <C-v><C-/>), nó sẽ xóa một lượng văn bản không thể đoán trước trên dòng. Tôi không hiểu đầy đủ về hành vi của nó, nhưng dường như chủ yếu có một loại hiệu ứng "tab đảo ngược" thay vì chèn một số khoảng trắng, nó sẽ xóa một số ký tự, nhưng đôi khi nó lại chèn ngẫu nhiên văn bản, vì vậy nó gây nhầm lẫn .
Braden hay nhất

10

Dấu phân cách đơn vị nằm trong phạm vi Ký tự điều khiển ASCII và do đó không (hoặc không thường xuyên) có biểu diễn trực quan.

Vim và một số biên tập viên khác hiển thị chúng, vì vậy bạn có thể chỉnh sửa chúng. Như bạn nhận thấy, cat -vhiển thị nó quá. Trang man hiển thị, đó -vlà dạng ngắn --show-nonprinting, khiến nó thay thế các ký tự không in bằng một biểu diễn có thể in được, không phải là nội dung gốc của tệp và do đó có thể gây ra sự cố, nếu đầu ra thực sự là một chương trình khác .

Đại diện mà bạn thấy đã gợi ý đó là ký tự điều khiển: ký tự được thêm vào ^là ký hiệu phổ biến cho Ctrl+ ký tự, là tổ hợp phím tạo ra ký tự này trong một thiết bị đầu cuối. Ctrl+ _sẽ cho phép bạn nhập dấu phân cách đơn vị trong vim, ví dụ. Nhưng một trình soạn thảo khác hoặc một số trình xem GUI có thể hiển thị mã hex, trình giữ chỗ hoặc thứ gì đó hoàn toàn khác.

Vì thiết bị đầu cuối của bạn không in các ký tự điều khiển, nó cũng không được sao chép khi chọn văn bản (các ký tự khoảng trắng như dòng mới và tab là một ngoại lệ ở đây, cũng là các ký tự điều khiển). Một ví dụ khác về các ký tự điều khiển trong thiết bị đầu cuối thường bị bỏ qua khi sao chép là mã màu, là một ESCký tự theo sau là mã để tô màu văn bản.

Vì vậy, để hiển thị các ký tự trên thiết bị đầu cuối của bạn, không có cách nào khác ngoài việc sử dụng một chương trình thay thế dấu phân cách đơn vị bằng một số ký tự có thể in được.


3

Một chút ở bên lề các câu trả lời (rất tốt) khác, nếu bạn muốn thay đổi chỉ ký tự điều khiển ^_khi hiển thị nội dung tập tin, bạn có thể muốn transliterate nó bằng cách sử dụng trtiện ích (và một chút của cú pháp bash tương thích) :

# Replace the control character US (^_) by *one* other character
$ cat my.file | tr $'\c_' ':'

Nếu bạn cần thay thế ký tự điều khiển đó bằng hình thức "mở rộng", bạn sẽ cần sedthay thế:

# Replace the control character US (^_) by any string
cat /tmp/f | sed s/$'\c_'/^_/g

Vui lòng lưu ý cú pháp $'\cX': cú pháp này thông báo (vỏ tương thích bash) của bạn để thay thế ký tự điều khiển tương ứng. Xem wikipedia để biết danh sách bí danh các ký tự điều khiển bằng cách sử dụng "ký hiệu dấu mũ". Nếu bạn không thích cú pháp đó, bạn có thể thích sử dụng ký hiệu bát phân $'\037'hoặc thập lục phân $'\x1f'thay thế.

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.