Bashのプロセス置換をHEREドキュメントと組み合わせる方法は?


14

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.

次のエラーが表示されます。

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
)

また、ここでドキュメントを引用したくない、つまりwriteし<'FOOBAR'たくないのは、その中に変数を代入したいからです。


本当にcat電話が必要ですか?呼び出しに残してみませんfmtか?
iruvar 14年

2
私はそれが不自然な例であることを認めなければなりません。私の実際のニーズはそれよりも複雑です。
ティムフリスケ14年

1
交換(Evenする"(Even"とうまくいくのは興味深いことです。についても同じです\(Even。解析バグのように見えます。Bashは、ここでのドキュメントを読んでいるコンテキストと、両方のコンテキストが互いに矛盾している場合に、中括弧を探しているコンテキストにまだあります。
ラファエルアーレンス14年

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

HEREDOC内での括弧の使用も問題ないようです:

例-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

これは単なる回避策です。プロセス置換を使用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ドキュメントの私の組み合わせがなぜ機能しないのかを理解したいと思います。答えはありますか?
ティムフリスケ14年

@TimFriske、bashこのサイトのウィザードのいずれか1つを延期する必要があります。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)

ありがとうございました!まさに私が探していたもの。
ピアストン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.