วิธีรวมกระบวนการทดแทนของ Bash เข้ากับเอกสาร HERE ได้อย่างไร


14

ใน Bash รุ่น 4.2.47 (1) - ปล่อยเมื่อฉันพยายามที่จะจัดรูปแบบข้อความที่จัดมาจาก HERE-dcoument ดังนี้:

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.

ฉันได้รับข้อผิดพลาดต่อไปนี้:

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
)

นอกจากนี้ฉันไม่ต้องการพูดที่นี่ - เอกสารคือเขียน<'FOOBAR'เพราะฉันยังต้องการที่จะมีตัวแปรที่ถูกทดแทนภายใน


คุณต้องการการcatโทรจริงๆเหรอ? ทำไมไม่ปล่อยไว้ที่การโทรfmt?
iruvar

2
ฉันต้องยอมรับว่ามันเป็นตัวอย่างที่วางแผนไว้ ความต้องการที่แท้จริงของฉันซับซ้อนกว่านั้น
Tim Friske

1
เป็นที่น่าสนใจว่าเมื่อคุณแทนที่(Evenด้วย"(Even"มันใช้งานได้ \(Evenมันเป็นเหมือนกันสำหรับ ดูเหมือนข้อผิดพลาดในการแยกวิเคราะห์ ทุบตียังอยู่ในบริบทที่มันกำลังมองหาวงเล็บปีกกาในขณะที่ยังอยู่ในบริบทของการอ่านเอกสารที่นี่และบริบททั้งสองขัดแย้งกัน
Raphael Ahrens

1
สิ่งนี้ได้รับการแก้ไขในbash4.3 โดยบังเอิญ
chepner

คำตอบ:


7

การทดแทนกระบวนการเทียบเท่ากับสิ่งนี้

ตัวอย่าง - กลไกของการทดแทนกระบวนการ

ขั้นตอนที่ # 1 - สร้าง Fifo เอาท์พุทมัน

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

ขั้นตอนที่ # 2 - อ่าน 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

การใช้ parens ภายใน HEREDOC นั้นก็ดูเหมือนว่า:

ตัวอย่าง - เพียงแค่ใช้ FIFO

ขั้นตอนที่ # 1 - ส่งออกไปยัง FIFO

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

ขั้นตอนที่ # 2 - อ่านเนื้อหาของ FIFO

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

ปัญหาที่ฉันเชื่อว่าคุณกำลังประสบอยู่ก็คือการทดแทนกระบวนการ<(...)ดูเหมือนจะไม่สนใจรังของ parens ภายใน

ตัวอย่าง - กระบวนการย่อย + HEREDOC ไม่ทำงาน

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

การหลบหนี parens ดูเหมือนจะเอาใจมันเล็กน้อย:

ตัวอย่าง - การหลบหนี parens

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

แต่ไม่ได้ให้สิ่งที่คุณต้องการจริงๆ การทำให้ความสมดุลของ parens ดูเหมือนว่าจะเอาใจมัน:

ตัวอย่าง - การทำ parens สมดุล

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

เมื่อใดก็ตามที่ฉันมีสตริงที่ซับซ้อนเช่นนี้เพื่อต่อสู้กับใน Bash ฉันมักจะสร้างพวกเขาก่อนเสมอเก็บไว้ในตัวแปรแล้วใช้พวกเขาผ่านตัวแปรแทนที่จะลองและสร้างซับหนึ่งที่ซับซ้อน บอบบาง.

ตัวอย่าง - ใช้ตัวแปร

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

จากนั้นให้พิมพ์:

$ echo "$var"
(one)
(two

อ้างอิง


3

นี่เป็นเพียงวิธีแก้ปัญหา ไพพ์fmtถึงcatแทนที่จะใช้การทดแทนกระบวนการ

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

1
ฉันลอง "วิธีแก้ปัญหา" ของคุณแล้วมันก็ใช้ได้ผลสำหรับฉัน ขอบคุณ แต่ฉันก็ยังต้องการที่จะเข้าใจว่าทำไมการรวมกันของเอกสาร HERE ที่ซ้อนกันภายในการทดแทนกระบวนการไม่ทำงาน คุณได้รับคำตอบหรือไม่?
Tim Friske

@ TimFriske ฉันจะต้องเลื่อนเวลาหนึ่งถึงหนึ่งในbashพ่อมดบนเว็บไซต์นี้ ความรู้ของฉันเกี่ยวกับ bash parser internals ถูก จำกัด ให้พูดอย่างน้อยที่สุด
iruvar

2

นี่เป็นคำถามเก่าและเมื่อคุณทราบว่านี่เป็นตัวอย่างที่วางแผนไว้ (และนั่นเป็นวิธีแก้ปัญหาที่ถูกต้องคือการใช้cat |หรือไม่จริงcatในกรณีนี้) ฉันจะโพสต์คำตอบสำหรับกรณีทั่วไป ฉันจะแก้มันโดยใส่มันลงในฟังก์ชั่นแล้วใช้มันแทน

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
}

แล้วใช้มัน

cat <(fmt-func)

ขอขอบคุณ! สิ่งที่ฉันกำลังมองหา
piarston
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.