Как присвоить значение heredoc переменной в Bash?
У меня есть многострочная строка (включая кавычки):
abc'asdf"
$(dont-execute-this)
foo"bar"''
Как я могу присвоить её переменной, используя heredoc в Bash?
Мне нужно сохранить переводы строк.
Я не хочу экранировать символы в строке, это было бы неудобно...
5 ответ(ов)
Вы можете избежать бесполезного использования cat
и лучше обработать несовпадающие кавычки с помощью следующего:
$ read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
Если вы не заключите переменную в кавычки при использовании echo
, новые строки будут потеряны. Кавычки помогают сохранить их:
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
Если вы хотите использовать отступы для лучшей читабельности в исходном коде, добавьте дефис после знаков меньше. Отступы должны быть выполнены только с помощью табуляций (без пробелов).
$ read -r -d '' VAR <<-'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
Если же вы хотите сохранить табуляции в содержимом результирующей переменной, вам нужно исключить табуляцию из IFS
. Маркер терминала для here document (EOF
) не должен иметь отступов.
$ IFS='' read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
Табуляции можно вставить в командной строке, нажав клавишу Tab
. Если вы используете редактор, в зависимости от него это может работать или вам, возможно, придется отключить функцию, которая автоматически преобразует табуляции в пробелы.
В команде read -r -d ''
параметры следующие:
-r
позволяет воспринимать обратные косые черты буквально вместо использования их для экранирования символов.-d
устанавливает первый символ следующего аргумента в качестве разделителя между записями (строками), вместо стандартного, которым является новая строка. В примере я устанавливаю разделитель как пустую строку, так что вся строка, переданная вread
, будет прочитана как одна запись.
Чтобы присвоить вывод команды cat
вашей переменной, используйте $()
следующим образом:
VAR=$(
cat <<'END_HEREDOC'
abc'asdf"
$(dont-execute-this)
foo"bar"''
END_HEREDOC
)
# этот командный вывод продублирует переменную с сохранением новых строк
echo "$VAR"
# этот командный вывод устранит новые строки (заменив их на пробелы)
echo $VAR
Обратите внимание, что необходимо начинать имя END_HEREDOC
с одинарных кавычек. Это предотвратит расширение содержимого heredoc, в результате чего dont-execute-this
не будет выполнена.
Также стоит отметить, что разделитель окончательного heredoc END_HEREDOC
должен находиться один на строке (поэтому скобка )
будет на следующей строке).
Спасибо за ответ @ephemient
.
Это вариация метода Денниса, выглядит более элегантно в скриптах.
Определение функции (версия для bash):
define(){ IFS=$'\n' read -r -d '' ${1} || true; }
Использование:
define VAR <<'EOF'
abc 'asdf " \$ $ \n $'\n'
$(dont-exec ute-this)
foo " bar " ' '
`bad bad ``
EOF
echo "$VAR"
Обновленная версия ksh с использованием цикла read
(также работает в bash):
function define { typeset a o=; while IFS= read -r a; do o+="$a"$'\n'; done; o=${o%?}; eval "$1=\$o"; }
Тесты (включают также версии, которые не удаляют последнюю новую строку): https://gist.github.com/ootada/e80b6d7fb86acdcda75d77eb7ade364c
Наслаждайтесь!
Ваша попытка использовать конструкцию VAR=<<END ... END
не работает, потому что вы перенаправляете стандартный ввод на что-то, что этого не учитывает, а именно на оператор присваивания.
Использование конструкции с обратными кавычками делает это:
export A=`cat <<END
sdfsdf
sdfsdf
sdfsfds
END
` ; echo $A
Однако это может вызвать некоторые проблемы, так как обратные кавычки могут помешать вам использовать это удобно. Лучше избегать использования обратных кавычек и вместо этого применять нотацию подстановки команд $(...)
.
Следующий пример работает корректно:
export A=$(cat <<END
sdfsdf
sdfsdf
sdfsfds
END
) ; echo $A
Таким образом, используйте $(...)
для подстановки команд, это более современный и понятный подход.
Это не так - вы, вероятно, просто вводитесь в заблуждение поведением команды echo
:
echo $VAR # удаляет переносы строк
echo "$VAR" # сохраняет переносы строк
Как работает "cat << EOF" в bash?
Как изменить цвет вывода echo в Linux
Передача параметров в функцию Bash
Расширение переменных внутри одинарных кавычек в команде Bash
Как разделить большой текстовый файл на меньшие файлы с равным количеством строк?