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 cat
in 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 fmt
to cat
statt 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