Wie kombiniere ich die Prozesssubstitution von Bash mit dem HERE-Dokument?

Wie kombiniere ich die Prozesssubstitution von Bash mit dem HERE-Dokument?

In der Bash-Version 4.2.47(1)-Release versuche ich, formatierten Text, der aus einem HERE-Dokument stammt, wie folgt zu verketten:

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.

Ich erhalte die folgende Fehlermeldung:

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
)

Außerdem möchte ich das HERE-Dokument nicht zitieren, also schreiben <'FOOBAR', da ich darin weiterhin Variablensubstitutionen haben möchte.

Antwort1

Dies ist eine alte Frage, und da Sie erkennen, dass dies ein konstruiertes Beispiel ist (und die richtige Lösung daher darin besteht, zu verwenden cat |oder catin diesem Fall eigentlich gar nicht), werde ich nur meine Antwort für den allgemeinen Fall posten. Ich würde es lösen, indem ich es in eine Funktion einfüge und diese stattdessen verwende.

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
}

und dann verwenden Sie das

cat <(fmt-func)

Antwort2

Die Prozesssubstitution entspricht in etwa diesem.

Beispiel - Mechanik der Prozesssubstitution

Schritt 1: Erstellen Sie ein FIFO und geben Sie es dort aus.

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

Schritt 2 - Lesen Sie das 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

Auch die Verwendung von Klammern innerhalb des HEREDOC scheint in Ordnung zu sein:

Beispiel - nur mit einem FIFO

Schritt 1 - Ausgabe an FIFO

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

Schritt 2 - Inhalt des FIFO lesen

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

Das Problem, auf das Sie meiner Meinung nach stoßen, besteht darin, dass die Prozesssubstitution <(...)die Verschachtelung der Klammern darin scheinbar nicht berücksichtigt.

Beispiel: Prozesssub + HEREDOC funktionieren nicht

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

Das Entkommen aus den Klammern scheint es ein wenig zu besänftigen:

Beispiel - Klammern entkommen

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

Aber es bringt Ihnen nicht wirklich das, was Sie wollen. Das Ausbalancieren der Klammern scheint es auch zu besänftigen:

Beispiel - Klammern ausgleichen

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

Wenn ich in Bash mit komplexen Zeichenfolgen wie dieser zu kämpfen habe, konstruiere ich sie fast immer zuerst, speichere sie in einer Variablen und verwende sie dann über die Variable, anstatt zu versuchen, einen kniffligen Einzeiler zu erstellen, der sich am Ende als inkompatibel erweist.

Beispiel: Verwenden einer Variablen

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

So drucken Sie es aus:

$ echo "$var"
(one)
(two

Verweise

Antwort3

Dies ist nur ein Workaround. Pipe fmtto catstatt Prozesssubstitution zu verwenden

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

verwandte Informationen