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.