Como combinar a substituição de processos do Bash com o documento HERE?

14

Na versão 4.2.47 (1) do Bash, quando eu tento criar um texto formatado que vem de um procedimento HERE, da seguinte forma:

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.

Estou tendo o erro a seguir:

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
)

Também não quero citar o documento HERE, ou seja <'FOOBAR', escrever , porque ainda quero que as variáveis ​​sejam substituídas nele.

Tim Friske
fonte
Você realmente precisa da catligação? Por que não deixar de ligar fmt?
Iruvar
2
Devo admitir que é um exemplo artificial. Minhas necessidades reais são mais complexas que isso.
Tim Friske
1
É interessante que quando você substituir (Evenpor "(Even"ele funcione. É o mesmo para \(Even. Parece um bug de análise. O Bash ainda está em um contexto em que está procurando aparelhos, enquanto também está lendo o documento aqui e ambos os contextos se contradizem.
Raphael Ahrens
1
Isso é corrigido em bash4.3, aliás.
chepner 9/09/15

Respostas:

7

A substituição do processo é aproximadamente equivalente a isso.

Exemplo - mecânica de substituição de processos

Etapa # 1 - faça um fifo, envie para ele

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

Etapa # 2 - leia o 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

O uso de parênteses no HEREDOC também parece bom:

Exemplo - apenas usando um FIFO

Etapa 1 - saída para FIFO

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

Etapa 2 - leia o conteúdo do FIFO

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

O problema, acredito que você esteja se deparando, é que a substituição do processo <(...)parece não se importar com o aninhamento de parênteses dentro dele.

Exemplo - processo sub + HEREDOC não funciona

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

Escapar dos parênteses parece apaziguar um pouco:

Exemplo - escapando parens

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

Mas realmente não dá o que você quer. Equilibrar as parênteses também parece apaziguar:

Exemplo - balanceamento de parênteses

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

Sempre que tenho strings complexas, como esta para lidar com o Bash, quase sempre as construo primeiro, armazenando-as em uma variável e depois as utilizo através da variável, em vez de tentar criar um liner complicado que acaba sendo frágil.

Exemplo - use uma variável

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

Em seguida, imprima-o:

$ echo "$var"
(one)
(two

Referências

slm
fonte
3

Esta é apenas uma solução alternativa. Canalize fmtpara, em catvez de usar substituição de 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
iruvar
fonte
1
Eu tentei sua "solução alternativa" e funcionaria para mim. Obrigado. Mas ainda quero entender por que minha combinação de um documento HERE aninhado dentro de uma substituição de processo não funciona. Você tem uma resposta?
Tim Friske
@ TimFriske, vou ter que adiar esse para um dos bashassistentes deste site. Meu conhecimento de internos do analisador festança é limitado para dizer o mínimo
Iruvar
2

Essa é uma pergunta antiga e, como você percebe que este é um exemplo artificial (e, portanto, que a solução correta é usar cat |ou, na verdade, não existe catneste caso), vou postar minha resposta no caso geral. Eu resolveria isso colocando-o em uma função e usando isso em seu lugar.

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 depois usar isso

cat <(fmt-func)
falstro
fonte
Obrigado! Exatamente o que eu estava procurando.
piarston