Sintaks multiline untuk pemipaan heredoc; apakah ini portabel?


132

Saya kenal dengan sintaks ini:

cmd1 << EOF | cmd2
text
EOF

tetapi baru saja menemukan bahwa bash memungkinkan saya untuk menulis:

cmd1 << EOF |
text
EOF
cmd2

(heredoc digunakan sebagai input ke cmd1, dan output dari cmd1 disalurkan ke cmd2). Sepertinya ini sintaks yang sangat aneh. Apakah ini portabel?


Saya datang ke sini untuk menemukan cara yang baik untuk membelah ini menjadi beberapa baris: big-long-command1 with lots of args << EOF | big-long-command2 with lots of args. "Sintaks ganjil" sepertinya cara terbaik.
PaulC

Satu kasus penggunaan yang nyaman untuk ini adalah ketika Anda mencoba untuk mengubah tabel yang dibatasi ruang menjadi yang dibatasi-tab sehingga Anda dapat menempelkannya di Google Spreadsheets. Anda tidak perlu membuat file sementara.
Sridhar Sarnobat

Yang pertama tidak bekerja untuk saya di z-shell. Saya tidak suka yang ke-2 karena itu mengasingkan | dari perintah, kehilangan idiomacy (?) dari jaringan pipa shell.
Sridhar Sarnobat

Jawaban:


104

Ya, standar POSIX memungkinkan ini. Menurut versi 2008:

Dokumen di sini akan diperlakukan sebagai satu kata yang dimulai setelah kata berikutnya <newline>dan berlanjut sampai ada garis yang hanya berisi pembatas dan a <newline>, tanpa <blank>karakter di antaranya. Kemudian di sini dokumen selanjutnya dimulai, jika ada.

Dan termasuk contoh beberapa "dokumen-sini" di baris yang sama:

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

Jadi tidak ada masalah melakukan pengalihan atau pipa. Contoh Anda mirip dengan sesuatu seperti ini:

cat file |
cmd

Dan tata bahasa shell (lebih jauh ke bawah pada halaman tertaut) mencakup definisi ini:

pipe_sequence    :                             command
                 | pipe_sequence '|' linebreak command

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

Jadi simbol pipa dapat diikuti oleh end-of-line dan masih dianggap sebagai bagian dari pipa.


26

Ya itu ada dalam tata bahasa shell POSIX. Anda juga dapat memiliki lebih dari satu dokumen di sini untuk perintah yang sama (beberapa contoh lain menggunakan dua catpemanggilan, tetapi ini juga berfungsi):

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

Ini dibuat-buat (menggunakan 2 di sini-docs untuk stdin), tetapi jika Anda berpikir untuk memberikan input untuk deskriptor file yang berbeda segera masuk akal.

Ada juga kemungkinan untuk menjatuhkan catseluruhnya . Mengapa tidak membuat dokumen di sini langsung tersedia untuk cmd:

cmd << EOF
input
here
EOF

`` `cat << EOF1 << EOF2 pertama di sini-doc EOF1 kedua di sini-doc EOF2` `` Hal di atas tidak berfungsi.
user1424739

@ user1424739 Tidak berfungsi di zsh dan bash saat ini. Abu dan ksh93 tampaknya hanya keluaran yang kedua di sini doc.
Jens

Mengapa downvote? Jika ada sesuatu yang tidak akurat, tolong beri saya kesempatan untuk memperbaiki.
Jens

Ini cukup manis saat digunakan sudo tee /etc/securefile.conf <<EOF.
dragon788

Pada versi bash apakah itu berfungsi? Menggunakan bash 4.4.19 (di ubuntu 18.04.02) dan bash 5.0 (docker image), saya hanya mendapatkan yang kedua di sini-doc. Atau mungkin ada opsi tertentu?
huelbois

17

Hmm, saya kira ya, menurut tes di bash dalam mode POSIX:

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

Hanya satu catatan kecil lainnya: jangan menaruh spasi setelah penutupan EOF. Prompt akan bertingkah aneh dan Anda akan bertanya-tanya apa yang salah
Sridhar Sarnobat

2
Menjalankan bash dalam mode POSIX menutup beberapa ekstensi, tetapi tidak dengan cara apa pun, bahkan hampir semuanya. Dengan demikian, sementara jawaban ini benar dalam hal apa yang POSIX izinkan, alasannya tidak mendukung hal itu dengan sangat efektif.
Charles Duffy

3

Hai, periksa ini, misalnya

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

salam

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.