Bagaimana cara menggabungkan proses substitusi Bash dengan dokumen HERE?

14

Dalam Bash versi 4.2.47 (1) - lepaskan ketika saya mencoba untuk menyatukan teks yang diformat yang berasal dari HERE-dokumen seperti:

cat <(fmt --width=10 <<FOOBAR
(I want the surrounding parentheses to be part of the HERE-document)
(Even the preceding unbalanced parenthesis should be part of it.
FOOBAR
) # I want this paranthesis to end the process substitution.

Saya mendapatkan kesalahan berikut:

bash: bad substitution: no closing `)' in <(fmt --width=10 <<FOOBAR
(I want the surrounding parentheses to be part of the HERE-document)
(Even the preceding unbalanced parenthesis should be part of it.
FOOBAR
)

Juga saya tidak ingin mengutip dokumen-SINI, yaitu menulis <'FOOBAR', karena saya masih ingin ada variabel yang diganti di dalamnya.

Tim Friske
sumber
Apakah Anda benar-benar membutuhkan cattelepon? Mengapa tidak membiarkannya menelepon fmt?
iruvar
2
Saya harus mengakui itu adalah contoh yang dibuat-buat. Kebutuhan saya yang sebenarnya lebih kompleks dari itu.
Tim Friske
1
Sangat menarik bahwa ketika Anda mengganti (Evendengan "(Even"itu berfungsi. Itu sama untuk \(Even. Tampak seperti bug penguraian. Bash masih dalam konteks yang sedang mencari kawat gigi sementara juga dalam konteks membaca dokumen di sini dan kedua konteks saling bertentangan.
Raphael Ahrens
1
Ini diperbaiki dalam bash4.3, kebetulan.
chepner

Jawaban:

7

Substitusi proses kira-kira setara dengan ini.

Contoh - mekanisme penggantian proses

Langkah # 1 - buat fifo, hasilkan

$ mkfifo /var/tmp/fifo1
$ fmt --width=10 <<<"$(seq 10)" > /var/tmp/fifo1 &
[1] 5492

Langkah # 2 - baca fifo

$ cat /var/tmp/fifo1
1 2 3 4
5 6 7 8
9 10
[1]+  Done                    fmt --width=10 <<< "$(seq 10)" > /var/tmp/fifo1

Penggunaan parens di dalam HEREDOC juga tampaknya OK:

Contoh - hanya menggunakan FIFO

Langkah # 1 - output ke FIFO

$ fmt --width=10 <<FOO > /var/tmp/fifo1 &
(one)
(two
FOO
[1] 10628

Langkah # 2 - baca konten FIFO

$ cat /var/tmp/fifo1
(one)
(two

Masalahnya, saya percaya Anda mengalami adalah bahwa proses substitusi,, <(...)tampaknya tidak peduli untuk bersarang parens di dalamnya.

Contoh - sub proses + HEREDOC tidak berfungsi

$ cat <(fmt --width=10 <<FOO
(one)
(two
FOO
)
bash: bad substitution: no closing `)' in <(fmt --width=10 <<FOO
(one)
(two
FOO
)
$

Lolos dari orangtua tampaknya menenangkannya, sedikit:

Contoh - melarikan diri orangtua

$ cat <(fmt --width=10 <<FOO                 
\(one\)
\(two
FOO
)
\(one\)
\(two

Tetapi tidak benar-benar memberi Anda apa yang Anda inginkan. Menjadikan parens seimbang juga tampaknya menenangkannya:

Contoh - menyeimbangkan parens

$ cat <(fmt --width=10 <<FOO
(one)
(two)
FOO
)
(one)
(two)

Setiap kali saya memiliki string yang kompleks, seperti ini untuk bersaing di Bash, saya hampir selalu akan membangunnya terlebih dahulu, menyimpannya dalam variabel, dan kemudian menggunakannya melalui variabel, daripada mencoba dan membuat beberapa liner rumit yang akhirnya menjadi rapuh.

Contoh - gunakan variabel

$ var=$(fmt --width=10 <<FOO
(one)
(two
FOO
)

Kemudian untuk mencetaknya:

$ echo "$var"
(one)
(two

Referensi

slm
sumber
3

Ini hanya solusi. Pipa fmtuntuk catbukannya menggunakan substitusi proses

fmt --width=10 <<FOOBAR | cat 
(I want the surrounding parentheses to be part of the HERE-document)
(Even the preceding unbalanced parenthesis should be part of it.
FOOBAR
iruvar
sumber
1
Saya mencoba "solusi" Anda dan itu akan berhasil untuk saya. Terima kasih. Tetapi saya masih ingin memahami mengapa kombinasi saya dari dokumen-HERE bersarang di dalam proses substitusi tidak bekerja. Sudahkah Anda mendapat jawaban?
Tim Friske
@TimFriske, saya harus menunda salah satu bashpenyihir di situs ini. Pengetahuan saya tentang bash parser internal terbatas untuk sedikitnya
iruvar
2

Ini adalah pertanyaan lama, dan ketika Anda menyadari bahwa ini adalah contoh yang dibuat-buat (dan dengan demikian bahwa solusi yang tepat adalah dengan menggunakan cat |atau sebenarnya, tidak catsama sekali dalam hal ini), saya hanya akan memposting jawaban saya untuk kasus umum. Saya akan menyelesaikannya dengan meletakkannya di fungsi dan menggunakannya sebagai gantinya.

fmt-func() {
    fmt --width=10 <<FOOBAR
(I want the surrounding parentheses to be part of the HERE-document)
(Even the preceding unbalanced parenthesis should be part of it.
FOOBAR
}

dan kemudian gunakan itu

cat <(fmt-func)
Falstro
sumber
Terima kasih! Persis apa yang saya cari.
piarston