Come combinare la sostituzione del processo di Bash con il documento HERE?


14

Nella versione 4.2.47 (1) di Bash, quando provo a catenare il testo formattato che proviene da un documento HERE in questo modo:

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.

Ottengo il seguente errore:

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
)

Inoltre non voglio citare il documento HERE, cioè scrivere <'FOOBAR', perché voglio ancora avere delle variabili da sostituire al suo interno.


Hai davvero bisogno della catchiamata? Perché non lasciarlo alla chiamata fmt?
Iruvar,

2
Devo ammettere che è un esempio inventato. I miei bisogni reali sono più complessi di così.
Tim Friske,

1
È interessante che quando si sostituisce (Evencon "(Even"esso funziona. È lo stesso per \(Even. Sembra un bug di analisi. Bash è ancora in un contesto in cui è alla ricerca di parentesi graffe, ma anche nel contesto della lettura del documento here ed entrambi i contesti si contraddicono a vicenda.
Raphael Ahrens,

1
Questo è risolto in bash4.3, per inciso.
Chepner,

Risposte:


7

La sostituzione del processo è approssimativamente equivalente a questo.

Esempio: meccanica della sostituzione del processo

Passaggio n. 1: crea un quinto, esegui l'output

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

Passaggio 2: leggi il quindicesimo

$ cat /var/tmp/fifo1
1 2 3 4
5 6 7 8
9 10
[1]+  Done                    fmt --width=10 <<< "$(seq 10)" > /var/tmp/fifo1

Anche l'uso dei genitori all'interno di HEREDOC sembra OK:

Esempio: basta usare un FIFO

Passaggio n. 1: output su FIFO

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

Step # 2 - leggi i contenuti di FIFO

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

Il guaio, credo che tu stia incontrando è che la sostituzione del processo <(...), non sembra preoccuparsi della nidificazione delle parentesi al suo interno.

Esempio: processo sub + HEREDOC non funziona

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

Scappare dai genitori sembra placarlo un po ':

Esempio: fuga di parentesi

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

Ma non ti dà davvero quello che vuoi. Anche il bilanciamento dei genitori sembra placarlo:

Esempio: bilanciamento delle parentesi

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

Ogni volta che ho stringhe complesse, come questa con cui confrontarmi in Bash, quasi sempre le costruirò prima, memorizzandole in una variabile, e poi le userò tramite la variabile, piuttosto che provare a creare una linea delicata che finisce per essere fragile.

Esempio: utilizzare una variabile

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

Quindi per stamparlo:

$ echo "$var"
(one)
(two

Riferimenti


3

Questa è solo una soluzione alternativa. Tubo fmta catinvece di utilizzare sostituzione di processo

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
Ho provato la tua "soluzione alternativa" e avrebbe funzionato per me. Grazie. Ma voglio ancora capire perché la mia combinazione di un documento HERE nidificato all'interno di una sostituzione di processo non funziona. Hai una risposta?
Tim Friske,

@ TimFriske, dovrò rinviare quello a uno dei bashmaghi su questo sito. La mia conoscenza degli interni di parser bash è limitata a dir poco
iruvar,

2

Questa è una vecchia domanda, e mentre ti rendi conto che questo è un esempio inventato (e quindi che la soluzione corretta è usare cat |o effettivamente, no cataffatto in questo caso), posterò la mia risposta per il caso generale. Lo risolverei inserendolo in una funzione e usandolo invece.

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
}

e poi usalo

cat <(fmt-func)

Grazie! Esattamente quello che stavo cercando.
Piarston,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.