Cú pháp đa dòng cho đường ống một di truyền; cái này có cầm tay không?


132

Tôi quen thuộc với cú pháp này:

cmd1 << EOF | cmd2
text
EOF

nhưng chỉ cần phát hiện ra rằng bash cho phép tôi viết:

cmd1 << EOF |
text
EOF
cmd2

(heredoc được sử dụng làm đầu vào cho cmd1 và đầu ra của cmd1 được dẫn đến cmd2). Đây có vẻ như là một cú pháp rất kỳ quặc. Nó có di động không?


Tôi đến đây để tìm một cách tốt để chia điều này thành nhiều dòng : big-long-command1 with lots of args << EOF | big-long-command2 with lots of args. "Cú pháp lẻ" có vẻ như là cách tốt nhất.
PaulC

Một trường hợp sử dụng thuận tiện cho việc này là khi bạn đang cố gắng chuyển đổi một bảng được phân tách không gian thành một bảng được phân định bằng tab để bạn có thể dán nó vào Bảng tính Google. Bạn sẽ không phải tạo một tập tin tạm thời.
Sridhar Sarnobat

Cái đầu tiên không hoạt động với tôi trong z-shell. Tôi không thích cái thứ 2 vì nó xa lánh | từ lệnh, mất thành ngữ (?) của đường ống vỏ.
Sridhar Sarnobat

Câu trả lời:


104

Có, tiêu chuẩn POSIX cho phép điều này. Theo phiên bản 2008:

Tài liệu ở đây sẽ được coi là một từ duy nhất bắt đầu sau từ tiếp theo <newline>và tiếp tục cho đến khi có một dòng chỉ chứa dấu phân cách và a <newline>, không có <blank>ký tự ở giữa. Sau đó, tài liệu tiếp theo ở đây bắt đầu, nếu có.

Và bao gồm ví dụ này về nhiều "tài liệu ở đây" trong cùng một dòng:

cat <<eof1; cat <<eof2
Hi,
eof1
Helene.
eof2

Vì vậy, không có vấn đề làm chuyển hướng hoặc đường ống. Ví dụ của bạn tương tự như thế này:

cat file |
cmd

Và ngữ pháp shell (tiếp tục xuống trên trang được liên kết) bao gồm các định nghĩa sau:

pipe_sequence    :                             command
                 | pipe_sequence '|' linebreak command

newline_list     :              NEWLINE
                 | newline_list NEWLINE
                 ;
linebreak        : newline_list
                 | /* empty */

Vì vậy, một biểu tượng đường ống có thể được theo sau bởi một dòng cuối và vẫn được coi là một phần của đường ống.


26

Vâng, đó là trong ngữ pháp vỏ POSIX. Bạn cũng có thể có nhiều hơn một tài liệu ở đây cho cùng một lệnh (một số ví dụ khác sử dụng hai cách catgọi, nhưng điều này cũng hoạt động):

cat <<EOF1 <<EOF2
first here-doc
EOF1
second here-doc
EOF2

Điều này là giả định (sử dụng 2 tài liệu ở đây cho stdin), nhưng nếu bạn nghĩ đến việc cung cấp đầu vào cho các mô tả tệp khác nhau thì ngay lập tức có ý nghĩa.

Cũng có khả năng bỏ cathoàn toàn . Tại sao không làm cho tài liệu ở đây có sẵn trực tiếp để cmd:

cmd << EOF
input
here
EOF

`` `cat << EOF1 << EOF2 đầu tiên ở đây-doc EOF1 thứ hai ở đây-doc EOF2` `` Cái trên không hoạt động.
user1424739

@ user1424739 Nó hoạt động trong zsh và bash hiện tại. Tro và ksh93 dường như chỉ xuất ra tài liệu thứ hai ở đây.
Jens

Tại sao các downvote? Nếu có điều gì đó không chính xác, xin vui lòng cho tôi cơ hội để khắc phục.
Jens

Điều này là khá ngọt ngào khi sử dụng sudo tee /etc/securefile.conf <<EOF.
dragon788

Nó hoạt động trên phiên bản bash nào? Sử dụng bash 4.4.19 (trên Ubuntu 18.04.02) và bash 5.0 (hình ảnh docker), tôi chỉ nhận được thứ hai ở đây-doc. Hoặc có thể có một lựa chọn cụ thể?
huelbois

17

Hmm, tôi cho là có, theo thử nghiệm trong bash ở chế độ POSIX:

$ bash --posix
$ cat <<EOF |
> ahoj
> nazdar
> EOF
> sed 's/a/b/'
bhoj
nbzdar

Chỉ cần một lưu ý nhỏ khác: không đặt bất kỳ khoảng trắng nào sau khi đóng EOF. Lời nhắc sẽ hành xử kỳ lạ và bạn sẽ tự hỏi cái quái gì là sai
Sridhar Sarnobat

2
Chạy bash trong chế độ POSIX sẽ tắt một số tiện ích mở rộng, nhưng không phải bằng bất kỳ phương tiện nào. Như vậy, trong khi câu trả lời này là chính xác về những gì POSIX cho phép, lý luận của nó không hỗ trợ điều đó rất hiệu quả.
Charles Duffy

3

Xin chào, kiểm tra cái này chẳng hạn

#!/bin/sh
( base32 -d | base64 -d )<<ENDOFTEXT
KNDWW42DNNSHS5ZXPJCG4MSVM5MVQVT2JFCTK3DELBFDCY2IIJYGE2JUJNHWS22LINVHQMCMNVFD
CWJQIIZVUV2JOVNEOVJLINTW6PIK
ENDOFTEXT

Trân trọng

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.