Назад | Перейти на главную страницу

Чистый способ записи сложной многострочной строки в переменную

Мне нужно написать сложный xml в переменную внутри сценария bash. Xml должен быть доступен для чтения внутри сценария bash, поскольку именно здесь будет находиться фрагмент xml, который не читается из другого файла или источника.

Итак, мой вопрос: если у меня есть длинная строка, которую я хочу, чтобы человек мог читать внутри моего сценария bash, как лучше всего это сделать?

В идеале хочу:

Можно ли это сделать с помощью EOF или чего-то еще, может ли кто-нибудь привести мне пример?

например

String = <<EOF
 <?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
EOF

Это поместит ваш текст в вашу переменную без необходимости экранировать кавычки. Он также будет обрабатывать несбалансированные кавычки (апострофы, т.е. '). Заключение в кавычки метки (EOF) предотвращает расширение параметров текста. В -d'' заставляет его читать несколько строк (игнорировать новые строки). read является встроенным в Bash, поэтому не требует вызова внешней команды, такой как cat.

IFS='' read -r -d '' String <<"EOF"
<?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
EOF

Вы почти были там. Либо вы используете кошка для сборки вашей строки или вы указываете всю строку (в этом случае вам придется избегать кавычек внутри вашей строки):

#!/bin/sh
VAR1=$(cat <<EOF
<?xml version="1.0" encoding='UTF-8'?>
<painting>
  <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's "Foligno" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>
EOF
)

VAR2="<?xml version=\"1.0\" encoding='UTF-8'?>
<painting>
  <img src=\"madonna.jpg\" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's \"Foligno\" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>"

echo "${VAR1}"
echo "${VAR2}"
#!/bin/sh

VAR1=`cat <<EOF
<?xml version="1.0" encoding='UTF-8'?>
<painting>
  <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's "Foligno" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>
EOF
`
echo "VAR1: ${VAR1}"

Это должно нормально работать в среде оболочки Bourne.

Еще один способ сделать то же самое ...

Мне нравится использовать переменные и специальные <<- кто падает табулирование в начале каждой строки, чтобы разрешить отступ скрипта:

#!/bin/bash

mapfile Pattern <<-eof
        <?xml version="1.0" encoding='UTF-8'?>
        <painting>
          <img src="%s" alt='%s'/>
          <caption>%s, painted in
          <date>%s</date>-<date>%s</date>.</caption>
        </painting>
        eof

while IFS=";" read file alt caption start end ;do
    printf "${Pattern[*]}" "$file" "$alt" "$caption" "$start" "$end"
  done <<-eof
        madonna.jpg;Foligno Madonna, by Raphael;This is Raphael's "Foligno" Madonna;1511;1512
        eof

предупреждение: здесь нет пустое пространство перед eof но только табулирование.

<?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
Some explanations:
  • mapfile читать полностью здесь документ в массиве.
  • синтаксис "${Pattern[*]}" преобразовать этот массив в строку.
  • я использую IFS=";" потому что нет ; в обязательных строках
  • Синтаксис while IFS=";" read file ... предотвращать IFS для изменения остальной части скрипта. В этом только read использовать модифицированный IFS.
  • нет вилки.

Во многих других ответах слишком много угловых случаев.

Чтобы быть абсолютно уверенным, что нет проблем с пробелами, табуляциями, IFS и т. Д., Лучше использовать конструкцию "heredoc", но кодировать содержимое heredoc с помощью uuencode как объяснено здесь:

https://stackoverflow.com/questions/6896025/#11379627.