Jak połączyć podstawienie procesu Basha z dokumentem TUTAJ?

14

W wersji Bash 4.2.47 (1) - wypuszczam, gdy próbuję catenate sformatowany tekst pochodzący z TUTAJ:

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.

Otrzymuję następujący błąd:

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
)

Nie chcę też cytować dokumentu TUTAJ, tj. Pisać <'FOOBAR', ponieważ nadal chcę, aby zmienne były w nim zastępowane.

Tim Friske
źródło
Czy naprawdę potrzebujesz catpołączenia? Dlaczego nie zostawić tego na telefon fmt?
iruvar
2
Muszę przyznać, że jest to wymyślony przykład. Moje rzeczywiste potrzeby są bardziej złożone.
Tim Friske,
1
Interesujące jest to, że podczas wymiany (Evenze "(Even"to działa. To samo dotyczy \(Even. Wygląda jak błąd analizy. Bash wciąż jest w kontekście, w którym szuka nawiasów klamrowych, a także w kontekście czytania tutaj doc i oba konteksty są ze sobą sprzeczne.
Raphael Ahrens,
1
bashNawiasem mówiąc, zostało to naprawione w 4.3.
chepner

Odpowiedzi:

7

Podstawienie procesu jest mniej więcej równoważne z tym.

Przykład - mechanika podstawienia procesu

Krok # 1 - stwórz fifo, wyślij do niego

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

Krok # 2 - przeczytaj piątkę

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

Korzystanie z parens w HEREDOC wydaje się również w porządku:

Przykład - wystarczy użyć FIFO

Krok # 1 - wysyłanie do FIFO

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

Krok # 2 - przeczytaj zawartość FIFO

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

Myślę, że problem polega na tym, że podstawienie procesu <(...)wydaje się nie dbać o zagnieżdżanie się w nim parenów.

Przykład - proces sub + HEREDOC nie działa

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

Ucieczka przed parenami wydaje się nieco uspokajać:

Przykład - ucieczkowe pareny

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

Ale tak naprawdę nie daje ci tego, czego chcesz. Wyrównanie parens również wydaje się łagodzić:

Przykład - równoważenie parens

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

Ilekroć mam skomplikowane łańcuchy, takie jak ten, z którymi walczę w Bash, prawie zawsze najpierw je zbuduję, przechowując je w zmiennej, a następnie używam ich za pomocą zmiennej, zamiast próbować stworzyć jakiś trudny jeden liniowiec, który ostatecznie jest kruchy.

Przykład - użyj zmiennej

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

Następnie, aby go wydrukować:

$ echo "$var"
(one)
(two

Bibliografia

slm
źródło
3

To tylko obejście. Rura fmtdo catzamiast stosowania procesu podstawienie

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
źródło
1
Wypróbowałem twoje „obejście” i zadziałałoby dla mnie. Dzięki. Ale nadal chcę zrozumieć, dlaczego moja kombinacja dokumentu TUTAJ zagnieżdżonego w podstawieniu procesu nie działa. Czy masz odpowiedź?
Tim Friske,
@ TimFriske, będę musiał odłożyć tego jednego do jednego z bashkreatorów na tej stronie. Moja wiedza na temat wewnętrznych parserów bash jest co najmniej ograniczona
iruvar
2

To stare pytanie i kiedy zdajesz sobie sprawę, że jest to wymyślony przykład (a zatem, że poprawnym rozwiązaniem jest użycie, cat |a właściwie wcale, catw tym przypadku wcale), po prostu opublikuję swoją odpowiedź na ogólny przypadek. Rozwiązałbym to, wprowadzając funkcję i używając jej zamiast tego.

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
}

a następnie użyj tego

cat <(fmt-func)
falstro
źródło
Dziękuję Ci! Dokładnie tego szukałem.
piarston