Echo các ký tự tab trong tập lệnh bash


313

Làm cách nào để lặp lại một hoặc nhiều ký tự tab bằng cách sử dụng tập lệnh bash? Khi tôi chạy mã này

res='       'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

Tôi hiểu rồi

res=[ x] # that is [<space>x]

Câu trả lời:


529
echo -e ' \t '

sẽ lặp lại 'dòng mới không gian tab không gian' ( -ecó nghĩa là 'cho phép giải thích các dấu gạch chéo ngược'):

$ echo -e ' \t ' | hexdump -C
00000000  20 09 20 0a                                       | . .|

Cảm ơn anh. Bạn đã giúp tôi tìm giải pháp này: res = '\ t \ t'x; echo -e '[' $ res ']'
kalyanji

2
Bạn có biết, tại sao echo -ekhông hoạt động từ Makefiles?
dma_k

23
Đó là bởi vì echo -ekhông phải là POSIX và makecác cuộc gọi /bin/shthường không phải là chương trình sử dụng sử dụng một cách tương tác và thường không được -ethực hiện. Đối với tính di động, sử dụng printf '\t'thay thế.
Jo So

Trong Darwin (macOS), mantrang cho echolệnh không đề cập đến tùy chọn -e. Tuy nhiên, tùy chọn này được chấp nhận.
ePi272314

75

Sử dụng printf, không echo.

Có nhiều phiên bản khác nhau của echolệnh. Có /bin/echo(có thể có hoặc không phải là phiên bản GNU Coreutils, tùy thuộc vào hệ thống) và echolệnh được tích hợp vào hầu hết các shell. Các phiên bản khác nhau có các cách khác nhau (hoặc không có cách nào) để chỉ định hoặc vô hiệu hóa các lối thoát cho các ký tự điều khiển.

printfmặt khác, có ít biến thể hơn nhiều. Nó có thể tồn tại như một lệnh, thông thường /bin/printf, và nó được tích hợp vào một số shell (bash và zsh có nó, tcsh và ksh không), nhưng các phiên bản khác nhau tương tự nhau nhiều hơn so với các phiên bản khác nhau echo. Và bạn không cần phải nhớ các tùy chọn dòng lệnh (với một vài ngoại lệ; GNU Coreutils printf chấp nhận --version--help, bash printf tích hợp chấp nhận -v varđể lưu trữ đầu ra trong một biến).

Ví dụ của bạn:

res='           'x # res = "\t\tx"
printf '%s\n' "[$res]"

Và bây giờ là lúc để tôi thừa nhận rằng nó echosẽ hoạt động tốt như ví dụ bạn đang hỏi về; bạn chỉ cần đặt dấu ngoặc kép xung quanh đối số:

echo "[$res]"

như kmkaplan đã viết (hai năm rưỡi trước, tôi mới nhận thấy!). Vấn đề với các lệnh ban đầu của bạn:

res='           'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

không với echo; đó là cái vỏ thay thế cái tab bằng một khoảng trắng trước khi echonhìn thấy nó.

echotốt cho đầu ra đơn giản, như echo hello world, nhưng bạn nên sử dụng printfbất cứ khi nào bạn muốn làm một cái gì đó phức tạp hơn. Bạn có thể bắt echođầu làm việc, nhưng mã kết quả có thể bị lỗi khi bạn chạy nó với một echotriển khai khác hoặc một trình bao khác.


1
Tôi thích cái này, nó cho phép tôi sử dụng kiến ​​thức về printf và tất cả các công cụ định dạng.
Arun

@JezenThomas: Nó không được đánh giá cao hơn vì nó trả lời câu hỏi theo cách khác so với yêu cầu. Câu hỏi đặc biệt đề cập đến tiếng vang và tiếng vang không phải là động từ mà là lệnh.
Paulo Neves

@PauloNeves: Tôi muốn nói rằng nó được sử dụng như một động từ trong câu hỏi: "Làm thế nào để tôi lặp lại một hoặc nhiều ký tự tab bằng cách sử dụng tập lệnh bash?"
Keith Thompson

34

Đặt chuỗi của bạn giữa hai dấu ngoặc kép:

echo "[$res]"

1
tương tự ở đây - đây là những gì tôi đã thử đầu tiên. -e hoạt động tốt mặc dù
froderik

2
@kmkaplan Làm việc cho tôi trong zsh - thất bại với tôi trong bash
Kal

34

Bạn cũng có thể thử:

echo Hello$'\t'world.

4
+1 cho giải pháp tổng quát hơn. Tôi đã sử dụng bash trong nhiều năm và tôi mới học được điều này ngay bây giờ!
Aryeh Leib Taurog

Đây là một câu tổng quát hơn nhiều so với câu trả lời được chấp nhận vì nó có thể được sử dụng mà không có tiếng vang.
jwan

22

bạn cần sử dụng cờ -e cho tiếng vang thì bạn có thể

echo -e "\t\t x"

16

Từ trang bash man:

Các từ có dạng $ 'chuỗi' được xử lý đặc biệt. Từ này mở rộng thành chuỗi, với các ký tự thoát dấu gạch chéo ngược được thay thế theo quy định của tiêu chuẩn ANSI C.

Vì vậy, bạn có thể làm điều này:

echo $'hello\tworld'

Tại sao điều này hoạt động trên cli nhưng không phải trong một kịch bản bash?
Freek

13

Sử dụng đúng nguyên văn tổ hợp phím, ^V( CTRL+V, C-v, bất cứ điều gì ).

Khi bạn nhập ^Vvào thiết bị đầu cuối (hoặc trong hầu hết các trình soạn thảo Unix), ký tự sau được lấy nguyên văn . Bạn có thể sử dụng điều này để nhập một ký tự tab theo nghĩa đen bên trong một chuỗi bạn đang lặp lại.

Một cái gì đó giống như các công việc sau đây:

echo "^V<tab>"     # CTRL+V, TAB

Tài liệu Bash ( qv , "trích dẫn-chèn")

trích dẫn-insert (Cq, Cv) Thêm ký tự tiếp theo mà bạn nhập vào nguyên văn dòng. Đây là cách chèn các chuỗi khóa như Cq chẳng hạn.

lưu ý phụ: theo điều này, ALT+TAB nên làm điều tương tự, nhưng tất cả chúng ta đều ràng buộc chuỗi đó với chuyển đổi cửa sổ để chúng ta không thể sử dụng nó

chèn thẻ (M-TAB) Chèn ký tự tab.

-

Lưu ý: bạn có thể sử dụng chiến lược này với tất cả các loại nhân vật khác thường. Giống như một chiếc xe ngựa trở về:

echo "^V^M"        # CTRL+V, CTRL+M

Điều này là do lợi nhuận vận chuyển là ASCII 13 và M là chữ cái thứ 13 của bảng chữ cái, vì vậy khi bạn nhập ^M, bạn sẽ nhận được ký tự ASCII thứ 13. Bạn có thể thấy nó hoạt động bằng cách sử dụng ls^M, tại một dấu nhắc trống, nó sẽ chèn trở lại vận chuyển, khiến cho dấu nhắc hành động giống như bạn nhấn return. Khi các ký tự này thường được giải thích, nguyên văn sẽ giúp bạn có được ký tự chữ.


1
Ước gì tôi có thể cung cấp cho bạn nhiều upvote cho cái này. Tôi không muốn sử dụng một -e trong các đối số của mình trong trường hợp này và điều này hoạt động rất tốt. Cảm ơn!
Aaron R.

"... hầu hết các biên tập viên Unix"? Đã thử nhập cái này với cả vi và emacs và nó cũng không cho kết quả mong muốn.
GreenMatt

Điều đó thật tuyệt! Và lưu lại ngày của tôi khi cố gắng sử dụng grepđể bắt các dòng có chứa các tabký tự.
Joël

11

Sử dụng echo để in các giá trị của các biến là một cạm bẫy Bash phổ biến. Liên kết tham khảo:

http://mywiki.wooledge.org/BashPitfall#echo_.24foo


Thật tuyệt, tôi thích "BashPit thác", mảnh vật liệu tuyệt vời và giảm bớt rất nhiều đau đớn từ công việc hàng ngày của tôi!
Jerry Tian

+1 vì điều này rất đúng. Nhưng lưu ý rằng chuỗi kalyanji bắt đầu bằng một [[và không chứa bất kỳ loại \ \ nào).
kmkaplan

2

Nếu bạn muốn sử dụng echo "a\tb"tập lệnh, bạn chạy tập lệnh dưới dạng:

# sh -e myscript.sh

Ngoài ra, bạn có thể cấp cho myscript.sh quyền thực thi và sau đó chạy tập lệnh.

# chmod +x myscript.sh
# ./myscript.sh

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.