如何将 Bash 的进程替换与 HERE 文档结合起来?

Tim*_*ske 16 bash process-substitution here-document

在 Bash 版本 4.2.47(1)-release 中,当我尝试连接来自 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.
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

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
)
Run Code Online (Sandbox Code Playgroud)

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

slm*_*slm 7

进程替换大致相当于这个。

示例 - 过程替换机制

第 1 步 - 制作一个 fifo,输出给它

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

第 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
Run Code Online (Sandbox Code Playgroud)

在 HEREDOC 中使用括号似乎也可以:

示例 - 仅使用 FIFO

步骤 #1 - 输出到 FIFO

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

步骤 #2 - 读取 FIFO 的内容

$ cat /var/tmp/fifo1
(one)
(two
Run Code Online (Sandbox Code Playgroud)

我相信您遇到的麻烦是过程替换 ,<(...)似乎并不关心其中的括号嵌套。

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

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

逃避括号似乎可以安抚它,有点:

示例 - 转义括号

$ cat <(fmt --width=10 <<FOO                 
\(one\)
\(two
FOO
)
\(one\)
\(two
Run Code Online (Sandbox Code Playgroud)

但并没有真正给你你想要的。使括号平衡似乎也可以安抚它:

示例 - 平衡括号

$ cat <(fmt --width=10 <<FOO
(one)
(two)
FOO
)
(one)
(two)
Run Code Online (Sandbox Code Playgroud)

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

示例 - 使用变量

$ var=$(fmt --width=10 <<FOO
(one)
(two
FOO
)
Run Code Online (Sandbox Code Playgroud)

然后打印它:

$ echo "$var"
(one)
(two
Run Code Online (Sandbox Code Playgroud)

参考


fal*_*tro 5

这是一个老问题,当您意识到这是一个人为的示例时(因此正确的解决方案是使用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
}
Run Code Online (Sandbox Code Playgroud)

然后用那个

cat <(fmt-func)
Run Code Online (Sandbox Code Playgroud)