2010-09-16 25 views
21

Định nghĩa của tài liệu tại đây là: http://en.wikipedia.org/wiki/Here_documentLàm thế nào để bạn gõ một tab trong một bash ở đây-tài liệu?

Làm cách nào bạn có thể nhập một tab trong tài liệu tại đây? Như thế này:

cat > prices.txt << EOF 
coffee\t$1.50 
tea\t$1.50 
burger\t$5.00 
EOF 

UPDATE:

Các vấn đề được đề cập trong câu hỏi này:

  1. Mở rộng tab nhân vật
  2. Trong khi không phải mở rộng dấu đôla
  3. Nhúng tài liệu tại đây trong một tệp chẳng hạn như tập lệnh
+0

trang web này cũng thú vị: http: //tldp.org/LDP/abs/h tml/abs-guide.html # GENERATESCRIPT –

Trả lời

13

Bạn có thể nhúng đây doc của bạn trong kịch bản của bạn và gán nó vào một biến mà không sử dụng một tập tin riêng biệt tại tất cả:

#!/bin/bash 
read -r -d '' var<<"EOF" 
coffee\t$1.50 
tea\t$1.50 
burger\t$5.00 
EOF 

Sau đó, printf hoặc echo -e sẽ mở rộng các ký tự \t thành các tab. Bạn có thể xuất nó vào một tập tin:

printf "%s\n" "$var" > prices.txt 

Hoặc gán giá trị của biến để tự sử dụng printf -v:

printf -v var "%s\n" "$var" 

Bây giờ var hoặc file prices.txt chứa các tab thực tế thay vì \t.

Bạn có thể xử lý ở đây doc của bạn khi nó được đọc thay vì lưu trữ nó trong một biến hoặc viết nó vào một tập tin:

while read -r item price 
do 
    printf "The price of %s is %s.\n" $item $price # as a sentence 
    printf "%s\t%s\n" $item $price     # as a tab-delimited line 
done <<- "EOF" 
    coffee $1.50 # I'm using spaces between fields in this case 
    tea $1.50 
    burger $5.00 
    EOF 

Lưu ý rằng tôi đã sử dụng <<- cho các nhà điều hành doc đây trong trường hợp này. Điều này cho phép tôi thụt lề các dòng của tài liệu ở đây để dễ đọc. Thụt lề phải chỉ bao gồm các tab (không có dấu cách).

+0

+1 Tôi đã học được nhiều nhất từ ​​câu trả lời này và nó giải quyết tất cả các vấn đề của tôi với tài liệu ở đây một số cách để sử dụng chúng hiệu quả. –

8

Đối với tôi, tôi nhập ctrl-V theo sau là ctrl-I để chèn tab vào bash shell. Điều này được xung quanh vỏ ngăn chặn các tab, mà nếu không có một ý nghĩa 'đặc biệt'. Ctrl-V theo sau là một tab cũng sẽ hoạt động.

Khi nhúng ký hiệu đô la vào tài liệu tại đây, bạn cần phải vô hiệu hóa nội suy của các biến trình bao hoặc tiền tố khác với dấu gạch chéo ngược để thoát (ví dụ: \$).

Sử dụng văn bản ví dụ của bạn tôi đã kết thúc với nội dung này trong prices.txt:

coffee\t.50 
tea\t.50 
burger\t.00 

$1$5 không được thiết lập. Nội suy có thể được tắt bằng cách trích dẫn terminator, ví dụ:

cat > prices.txt <<"EOF" 
+0

+1 Cảm ơn bạn đã trả lời. Điều gì sẽ xảy ra nếu tôi muốn lưu trữ tài liệu ở đây trong một tệp để chạy sau này? Ví dụ: nếu tôi muốn sử dụng tài liệu ở đây để cung cấp tệp ví dụ tôi có thể khi chạy tập lệnh paticular và lưu trữ tài liệu ở đây đã nhận xét trong cùng một tệp với tập lệnh để tham khảo sau này? –

+0

@D W - Tôi không chắc chắn tôi làm theo những gì bạn đang yêu cầu ở đó - bạn chắc chắn có thể nhúng tài liệu ở đây vào tập lệnh. –

+0

Cảm ơn bạn đã đề cập đến giải pháp để bao gồm các ký hiệu đô la trong tài liệu tại đây mà không yêu cầu họ giải thích. –

15
TAB="$(printf '\t')" 

cat > prices.txt << EOF 
coffee${TAB}\$1.50 
tea${TAB}\$1.50 
burger${TAB}\$5.00 
EOF 
+0

+1 Cảm ơn bạn đã đề cập đến một giải pháp dễ dàng để bao gồm các tab trong tài liệu tại đây. –

+5

Phím tắt cụ thể bash sẽ là 'TAB = $ '\ t'', lạm dụng các tính năng gettext. – Daenyth

+0

@Denyeny, Cảm ơn bạn đã tip, đó là một cách thanh lịch hơn. –

2

Tôi lưu ý rằng câu trả lời đúng đã được đưa ra, nhưng tôi đang cố tóm tắt thành câu trả lời ngắn gọn hơn.

1. Không có gì để ngăn bạn không có các ký tự tab theo ngữ cảnh trong tài liệu tại đây.

Để nhập một tab chữ vào lời nhắc Bash, bạn cần phải thoát khỏi nó. Ký tự thoát là ctrl-V (trừ khi bạn có các ràng buộc tùy chỉnh để ghi đè điều này).

$ echo -n 't<ctrl-v><tab>ab' | hexdump -C 
00000000 74 09 61 62          |t.ab| 
00000004 

Trong hầu hết các biên tập viên của bất kỳ lập trình viên, nó phải là tầm thường để chèn một ký tự tab chữ (mặc dù một số biên tập viên có thể muốn thoát, quá. Trong Emacs, ctrl-Q TAB chèn một tab đen).

Để rõ ràng, có thể tốt hơn nên sử dụng loại thoát nào đó thay vì ký tự tab theo nghĩa đen. Trong Bash, cú pháp chuỗi $ '...' thuận tiện cho việc này.

2. Để ngăn việc mở rộng biến, báo giá tất cả các ký hiệu đô la hoặc đặt dấu kết thúc tài liệu tại đây trong dấu ngoặc kép.

$ hexdump -C <<HERE 
> t<ctrl-v><tab>\$ab 
HERE 
00000000 74 09 24 61 62 0a         |t.$ab.| 
00000006 

$ hexdump -C <<'HERE' 
> t<ctrl-v><tab>$ab 
HERE 
00000000 74 09 24 61 62 0a         |t.$ab.| 
00000006 

Trong bối cảnh này, việc bạn sử dụng dấu ngoặc đơn hoặc dấu ngoặc kép không quan trọng.

3. Tôi không chắc mình hiểu được câu hỏi con này. Mục đích của tài liệu ở đây là nhúng nó vào một tập lệnh. Ví dụ trước minh họa cách chuyển một tài liệu ở đây sang hexdump trong một kịch bản lệnh hoặc tại dòng lệnh.

Nếu bạn muốn sử dụng cùng một tài liệu ở đây nhiều lần, không có cách nào đơn giản để làm điều đó trực tiếp. Tập lệnh có thể viết một tài liệu ở đây vào một tệp tạm thời, sau đó chuyển tệp tạm thời đó cho nhiều lệnh, sau đó xóa tệp tạm thời. (Hãy cẩn thận sử dụng trap để xóa tệp tạm thời cũng trong trường hợp tập lệnh bị gián đoạn.)

Bạn cũng có thể đặt nội dung của tài liệu này vào biến và nội suy đó.

# Note embedded newlines inside the single quotes, 
# and the use of $'...\t...' to encode tabs 
data=$'coffee\t$1.50 
tea\t$1.50 
burger\t$5.00' 

# Run Word Count on the data using a here document 
wc <<HERE 
$data 
HERE 

# Count number of tab characters using another here document with the same data 
grep -c $'\t' <<HERE 
$data 
HERE 

Bạn tương đương có thể sử dụng echo -E "$data" | wc; echo -E "$data" | grep -c $'\t' nhưng sử dụng tiếng vang không phải là rất thanh lịch và có thể ít di động (mặc dù nếu mục tiêu của bạn là bash, tất cả echos nên giống nhau. Nếu mục tiêu của bạn là Bourne shell nói chung, có lẽ bạn cũng dành một quá trình bên ngoài cho mỗi tiếng vang).

1

Re: Câu hỏi con # 3, tôi đọc câu hỏi này như sau:

"[W] mũ nếu tôi muốn [...] lưu trữ ở đây-doc nhận xét trong cùng một tập tin như kịch bản để tham khảo sau này? "

Sử dụng tên tập lệnh làm đầu ra của tài liệu tại đây, chắp thêm thay vì thay thế, giả sử người thực thi cũng có quyền ghi. Nhận xét của Shell không được diễn giải trong một khối tài liệu ở đây.

_thisline=${LINENO} 
cat <<EOF >>$0 
#====== $(date) ========= 
#On this run, these variable values were used as of line ${_thisline}: A=${A}, B=${B}, B=${C} 

EOF 

Theo cách tương tự, bạn có thể sử dụng một doc vào đây để viết ra một kịch bản mới mở rộng biến để giá trị, exec nó, và sau đó bạn có một hồ sơ chính xác về những gì đã được chạy thay vì phải theo dõi các mã.

5

Như những người khác đã nói, bạn có thể nhập CTRL-V rồi tab để chèn một tab khi nhập.

Bạn cũng có thể vô hiệu hóa bash tab hoàn thành tạm thời, ví dụ nếu bạn muốn dán văn bản hoặc nếu bạn muốn gõ một chặng đường dài ở đây-doc với nhiều tab:

bind '\C-i:self-insert'  # disable tab-completion 

# paste some text or type your here-doc 
# note you don't use "\t" you just press tab 

bind '\C-i:complete'  # reenable tab-completion 

EDIT: Nếu bạn' trên máy Mac và sử dụng iTerm 2, hiện tại có tùy chọn "Dán bằng tab chữ" cho phép dán mã bằng các tab vào dòng lệnh bash.

0

Một đơn giản và giải pháp trực tiếp cho vấn đề ban đầu là sử dụng $ (echo $ '...') thành ngữ:

cat > prices.txt << EOF 
$(echo $'coffee\t$1.50') 
$(echo $'tea\t$1.50') 
$(echo $'burger\t$5.00') 
EOF 
0

Nếu bạn sử dụng một công cụ như sed và trích dẫn delimiter (EOF), mọi thứ có thể nhận được đơn giản hơn:

sed 's/\\t/\t/g' > prices.txt << 'EOF' 
coffee\t$1.50 
tea\t$1.50 
burger\t$5.00 
EOF 
  • Trích dẫn EOF ngăn chặn tham số) mở rộng dấu đô la (.
  • sed chuyển đổi '\ t' thành các ký tự tab.
  • Nếu bạn có patters như \\t trong tài liệu tại đây của mình, thì bạn sẽ cần một lệnh gọi sed phức tạp hơn như: sed -e 's/\\t/\t/g' -e 's/\\\t/\\t/g'.
1

Các tab được dán vào một heredoc biến mất, vì bash vẫn đang diễn giải chúng dưới dạng ký tự đặc biệt đánh dấu sự bắt đầu chuỗi/yêu cầu tự động hoàn thành.

Nếu bạn muốn dán nhanh một heredoc trong trình bao hiện tại, bạn có thể thực hiện việc này bằng cách tắt tự động hoàn thành cho vòng đời của trình bao hiện tại.

Đây là những gì xảy ra với bình thường tự động hoàn thành nếu bạn dán một heredoc chứa tab:

$ cat <<EOF 
TABAFTERTABBEFORE 
TABAFTERTABBEFORE 
TABAFTERTABBEFORE 
TABAFTERTABBEFORE 
TABAFTERTABBEFORE 
EOF 
TABAFTERTABBEFORE 
TABAFTERTABBEFORE 
TABAFTERTABBEFORE 
TABAFTERTABBEFORE 
TABAFTERTABBEFORE 

Chạy lệnh này:

bind "set disable-completion on"

Dán một lần nữa và các tab của bạn được giữ lại:

$ cat <<EOF 
> TABAFTER  TABBEFORE 
> TABAFTER  TABBEFORE 
> TABAFTER  TABBEFORE 
> TABAFTER  TABBEFORE 
> TABAFTER  TABBEFORE 
> EOF 
TABAFTER TABBEFORE 
TABAFTER TABBEFORE 
TABAFTER TABBEFORE 
TABAFTER TABBEFORE 
TABAFTER TABBEFORE 
Các vấn đề liên quan