如何将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
)

我也不想引用HERE文档,即write <'FOOBAR',因为我仍然想在其中替换变量。


您真的需要cat电话吗?为什么不打电话fmt呢?
iruvar

2
我必须承认这是一个人为的例子。我的实际需求比这更复杂。
Tim Friske 2014年

1
有趣的是,当您替换它时(Even"(Even"它可以工作。相同\(Even。看起来像一个解析错误。Bash仍在寻找括号的上下文中,同时在阅读此文档的上下文中,两个上下文相互矛盾。
拉斐尔·阿伦斯

1
bash顺便说一句,此问题已在4.3中修复。
chepner 2015年

Answers:


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

在HEREDOC中使用parens似乎也可以:

示例-仅使用FIFO

步骤#1-输出到FIFO

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

步骤#2-读取FIFO的内容

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

我认为您遇到的麻烦是,流程替换(<(...))似乎并不关心内部的嵌套。

示例-进程子+ HEREDOC不起作用

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

逃避父母的抚慰似乎有些安抚:

示例-转义括号

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

但是并没有真正给你想要的东西。使括号保持平衡似乎也令人安心:

示例-平衡括号

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

每当我有复杂的字符串(例如在Bash中要使用的字符串)时,我几乎总是会首先构造它们,将它们存储在变量中,然后通过变量使用它们,而不是尝试制作一些棘手的内衬而最终成为脆弱。

示例-使用变量

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

然后打印:

$ echo "$var"
(one)
(two

参考文献


3

这只是一个解决方法。管fmtcat代替使用进程替换

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 2014年

@TimFriske,我将不得不将其推迟bash到此站点上的向导之一。我对bash解析器内部的了解至少可以说是
不对

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.