In thập phân sang ký tự ascii, lệnh của tôi không xuất ra như dự định


14

Tôi muốn xuất một chuỗi gồm tất cả các ký tự ascii bằng lệnh sau

for i in `seq 32 127`; do printf "%c" $i; done

Đầu ra của lệnh trên là:

33333334444444444555555555566666666667777777777..............

Đây là chữ số đầu tiên (từ bên trái) của mỗi số.

Nhìn qua trang web này, tôi đã tìm thấy câu trả lời cho vấn đề của mình Làm thế nào để in tất cả các ký tự ASCII có thể in trong CLI? , tuy nhiên tôi vẫn không hiểu tại sao đoạn trích ban đầu của mình không xuất ra các ký tự ascii như dự định.


1
POSIX ra lệnh này, đây là một comp.unix.shellchủ đề về lý do tại sao đó là điều đúng;)
sr_

@sr_ Cảm ơn bạn đã chỉ ra chủ đề. Nó đã có lời giải thích mà tôi đang tìm kiếm.
Ifthikhan

Câu trả lời:


13

Bạn không thể in trực tiếp mã ascii bằng cách sử dụng printf "%c" $inhư trong C.

Trước tiên, bạn phải chuyển đổi giá trị thập phân của i thành giá trị bát phân của nó và sau đó bạn phải in nó bằng cách sử dụng printfvà đặt \trước các giá trị bát phân tương ứng của chúng.

Để in A, bạn phải chuyển đổi số thập phân 65 thành số bát phân, tức là 101, và sau đó bạn phải in giá trị bát phân đó thành:

printf "\101\n"

Điều này sẽ in A.

Vì vậy, bạn phải sửa đổi nó thành:

for i in `seq 32 127`; do printf \\$(printf "%o" $i);done;

Nhưng bằng cách sử dụng, awkbạn có thể in trực tiếp như trong ngôn ngữ C

awk 'BEGIN{for(i=32;i<=127;i++)printf "%c",i}';echo

7
Trong bashzshđiều này có thể được thực hiện mà không có vòng lặp và không có lệnh bên ngoài : printf $(printf '\%o' {32..127}).
thao tác

@manatwork: ya chính xác..cảm ơn rất nhiều vì đã chỉ ra nó ..
pradeepchhetri

1
@pradeepchhetri: Cảm ơn bạn đã phản hồi chi tiết và dường như nó bao gồm hầu hết các chi tiết cần thiết (do đó tôi chọn câu trả lời của bạn). Tuy nhiên, tôi đoán rằng nó đã bỏ lỡ một thông tin quan trọng có thể tìm thấy trong thông báo sau tại unix.derkeiler.com/Newsgroups/comp.unix.shell/2007-07/ . Nó tuyên bố rằng "Các toán hạng đối số sẽ được coi là các chuỗi nếu chỉ định chuyển đổi tương ứng là b, c hoặc s ..."
Ifthikhan

Không phải là (char)(127)backspace hoặc một cái gì đó như thế. Dù đó là gì, nó xuất hiện dưới dạng một trong các hộp hex hoặc bất cứ thứ gì chúng được gọi. Nếu bạn chỉ muốn "có thể in" (nghĩa là có thể đọc được), chỉ cần truy cập 126. Ngoài ra, suy nghĩ tốt với bát phân. Thật khéo léo; Tôi đã suy nghĩ về mặt thập lục phân (như printf '\x%x; {32..126}... hoặc 127, tôi đoán, vì tất cả các bạn cũng đã làm điều đó), nhưng nó không hoạt động. Octal tiết kiệm trong ngày! :) Cuối cùng, @ Ifthikhan, tôi không chắc ý của bạn là gì. awkthường sử dụng các lệnh kiểu C và không nơi nào khác được %csử dụng. Sử dụng số bát phân khác với sử dụng các ký tự một byte.
Dylan

3

%c Giải thích đối số liên quan là char: chỉ ký tự đầu tiên của đối số đã cho được in

Bạn dường như đã có một cách để in chúng, nhưng đây là một biến thể.

for i in `seq 32 127`; do printf "\x$(printf "%x" $i) $i"; done

0

Bạn cần printf, nhưng chỉ một lần; bạn có thể thay thế một lần sử dụng printfbằng các echochuỗi thoát Bash đơn giản và hiệu quả hơn :

Với hexagesimals:

for i in `seq 32 127`; do
  echo -ne \\x$(printf %02x $i)
done

Với quãng tám:

for i in `seq 32 127`; do
  echo -ne \\0$(printf %03o $i)
done
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.