В Bash версии 4.2.47(1)-release при попытке объединить форматированный текст, полученный из HERE-dcoument, следующим образом:
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.
Я получаю следующую ошибку:
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
)
Также я не хочу цитировать HERE-документ, т.е. писать <'FOOBAR'
, потому что я все равно хочу, чтобы в нем были подставлены переменные.
решение1
Это старый вопрос, и как вы понимаете, это надуманный пример (и, таким образом, правильным решением будет использовать cat |
or, на самом деле, cat
вообще не использовать в этом случае), я просто опубликую свой ответ для общего случая. Я бы решил его, поместив его в функцию и используя ее вместо этого.
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
}
и затем использовать это
cat <(fmt-func)
решение2
Процесс замещения примерно эквивалентен этому.
Пример - механика замещения процесса
Шаг №1 - создаем fifo, выводим в него
$ mkfifo /var/tmp/fifo1
$ fmt --width=10 <<<"$(seq 10)" > /var/tmp/fifo1 &
[1] 5492
Шаг №2 - прочитайте 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
Использование скобок в HEREDOC также кажется допустимым:
Пример — простое использование FIFO
Шаг №1 — вывод в FIFO
$ fmt --width=10 <<FOO > /var/tmp/fifo1 &
(one)
(two
FOO
[1] 10628
Шаг №2 — чтение содержимого FIFO
$ cat /var/tmp/fifo1
(one)
(two
Проблема, с которой, как я полагаю, вы столкнулись, заключается в том, что процесс подстановки, <(...)
похоже, не учитывает вложенность скобок внутри него.
Пример - процесс sub + HEREDOC не работают
$ cat <(fmt --width=10 <<FOO
(one)
(two
FOO
)
bash: bad substitution: no closing `)' in <(fmt --width=10 <<FOO
(one)
(two
FOO
)
$
Кажется, избавление от скобок немного его успокаивает:
Пример - экранирование скобок
$ cat <(fmt --width=10 <<FOO
\(one\)
\(two
FOO
)
\(one\)
\(two
Но на самом деле не дает вам того, что вы хотите. Сбалансированность скобок также, кажется, успокаивает его:
Пример - балансирующие скобки
$ cat <(fmt --width=10 <<FOO
(one)
(two)
FOO
)
(one)
(two)
Всякий раз, когда мне приходится иметь дело со сложными строками, такими как эта, в Bash, я почти всегда сначала создаю их, сохраняю в переменной, а затем использую их через эту переменную, вместо того чтобы пытаться придумать какой-то сложный однострочный код, который в итоге оказывается хрупким.
Пример - использование переменной
$ var=$(fmt --width=10 <<FOO
(one)
(two
FOO
)
Затем, чтобы распечатать его:
$ echo "$var"
(one)
(two
Рекомендации
решение3
Это просто обходной путь. Вместо использования подстановки процесса fmt
используйте конвейерcat
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