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.


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


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

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)

Obrigado! Exatamente o que eu estava procurando.
— piarston
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.