Wie kann man die Prozessersetzung von Bash mit HERE-document kombinieren?


14

In Bash Version 4.2.47 (1) -Release, wenn ich versuche, 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 folgenden Fehler:

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
)

Auch möchte ich das HERE-Dokument nicht zitieren, dh schreiben <'FOOBAR', weil ich immer noch Variablen haben möchte, die darin ersetzt werden.


Benötigen Sie den catAnruf wirklich ? Warum nicht beim Anrufen belassen fmt?
Iruvar

2
Ich muss zugeben, dass es ein erfundenes Beispiel ist. Meine tatsächlichen Bedürfnisse sind komplexer.
Tim Friske

1
Es ist interessant , dass , wenn Sie ersetzen (Evenmit "(Even"es funktioniert. Es ist dasselbe für \(Even. Sieht aus wie ein Parsing-Bug. Bash ist immer noch in einem Kontext, in dem es nach geschweiften Klammern sucht, während sich beide Kontexte beim Lesen des Dokuments widersprechen.
Raphael Ahrens

1
Dies ist bashübrigens in 4.3 behoben .
Chepner

Antworten:


7

Die Prozesssubstitution entspricht in etwa dieser.

Beispiel - Mechanik der Prozesssubstitution

Schritt # 1 - mache ein FIFO, gib es aus

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

Schritt 2 - Lies 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

Die Verwendung von Parens im HEREDOC scheint ebenfalls 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

Ich glaube, Sie stoßen auf das Problem, dass die Prozessersetzung <(...)nicht für die Verschachtelung von Parens zu sorgen scheint.

Beispiel - Prozess Sub + HEREDOC funktioniert nicht

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

Es scheint ein wenig zu beruhigen, den Eltern zu entkommen:

Beispiel - Flucht vor Eltern

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

Aber gibt dir nicht wirklich das, was du willst. Das Gleichgewicht der Eltern scheint auch zu beschwichtigen:

Beispiel - Balancing Parens

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

Wenn ich komplexe Zeichenfolgen habe, mit denen ich in Bash zu kämpfen habe, werde ich sie fast immer zuerst konstruieren, sie in einer Variablen speichern und sie dann über die Variable verwenden, anstatt zu versuchen, einen kniffligen Liner zu konstruieren, der letztendlich existiert fragil.

Beispiel - Verwenden Sie eine Variable

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

Dann zum Ausdrucken:

$ echo "$var"
(one)
(two

Verweise


3

Dies ist nur eine Problemumgehung. Pipe fmtto catanstelle von Prozessersetzung

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
Ich habe versucht, Ihr Problem zu umgehen, und es würde für mich funktionieren. Vielen Dank. Dennoch möchte ich verstehen, warum meine Kombination eines in einer Prozessersetzung verschachtelten HERE-Dokuments nicht funktioniert. Hast du eine Antwort?
Tim Friske

@TimFriske, ich muss das einem der bashZauberer auf dieser Seite aufschieben . Mein Wissen über Bash-Parser-Interna ist, gelinde gesagt, begrenzt
iruvar

2

Dies ist eine alte Frage, und wie Sie feststellen, ist dies ein erfundenes Beispiel (und somit ist die richtige Lösung zu verwenden) cat |cat in diesem Fall " Nein" zu verwenden), werde ich nur meine Antwort für den allgemeinen Fall veröffentlichen. Ich würde es lösen, indem ich es in eine Funktion stecke und diese stattdessen benutze.

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 benutze das

cat <(fmt-func)

Vielen Dank! Genau das, wonach ich gesucht habe.
Piarston
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.