我需要在bash脚本中的变量中编写一些复杂的xml。 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


评论

我敢打赌,您将再次将数据转储到流中。当您可以使事情变得更复杂并使用流时,为什么将其存储在变量中?

也可以看到此信息:带有多余空格的多行字符串(保留缩进)

#1 楼

这会将您的文本放入变量中,而无需转义引号。它还将处理不平衡的报价(撇号,即')。在前哨(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


评论


cat是一个外部命令。不使用它可以节省时间。另外,有些人的哲学是,如果您使用的猫少于两个参数,“ Ur doin'it错”(这与“猫的无用使用”不同)。

–丹尼斯·威廉姆森
2009年10月9日,0:03

并且永远不会缩进第二个EOF ....(涉及多个表以敲击刘海)

–IljaBek
2012年5月18日19:40

我在设置-e时尝试使用以上语句。似乎read总是返回非零值。您可以通过使用!重新添加 .......

–krissi
2012年11月8日10:56

@DennisWilliamson:Shell中的“正确”错误处理非常繁琐。 set -e是不完善的,偶尔会造成陷阱,但会使脚本更加可靠。

–安德鲁(Andrew)
2012年11月19日22:42

并且,如果您正在使用此多行String变量写入文件,请将该变量放在“ QUOTES”周围,例如echo“ $ {String}”> /tmp/multiline_file.txt或echo“ $ {String}” | tee /tmp/multiline_file.txt。花了我一个多小时才找到。

– Aditya
14年4月20日在16:16

#2 楼

你快到了。您可以使用cat组装字符串,也可以对整个字符串加引号(在这种情况下,必须对字符串内的引号进行转义):

#!/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}"


评论


不幸的是,“ Raphael's”中的撇号使第一个无效。

–丹尼斯·威廉姆森
09-10-8在12:37

两项任务最终都对我有用。 VAR1中的单引号应该没有问题(至少对于bash而言不是)。也许您被语法高亮误导了?

– joschi
09年10月8日在21:13

它可以在脚本中工作,但不能在Bash提示符下工作。抱歉,不清楚。

–丹尼斯·威廉姆森
09年10月9日在6:08

最好将EOF引用为“ EOF”或“ EOF”,否则将解析shell变量。

–斯坦尼斯拉夫·德·埃夫图申科
18年5月6日在13:43



确保用引号将“ $ VAR1”回显以检查您的工作,否则将不会打印换行符。

–rjurney
20-09-24在3:04

#3 楼

#!/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外壳环境中应该可以正常工作

评论


+1此解决方案允许变量替换,例如$ {foo}

– Offirmo
2012年9月27日下午16:54

上行:sh兼容。缺点:不推荐使用bash来禁止反引号。现在,如果我必须在sh和bash之间进行选择...

–辛尼泽
13年9月26日在22:55

从什么时候起就不再推荐反引号了?只是好奇

–亚历山大·米尔斯(Alexander Mills)
18年4月21日在1:50

#4 楼

另一种执行此操作的方法...

我喜欢使用变量和特殊的<<-,它们在每一行的开头都删除制表符以允许脚本缩进:

#!/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>


一些解释:


mapfile将整个此处的文档读取到数组中。
语法"${Pattern[*]}"确实将此数组转换为字符串。
我使用IFS=";"是因为必需的字符串中没有;
语法while IFS=";" read file ...阻止了IFS转换为字符串在脚本的其余部分进行修改。在这种情况下,只有read会使用经过修改的IFS
没有前叉。


评论


请注意,mapfile需要Bash 4或更高版本。语法“ $ {Pattern [*]}”使用引号将数组转换为字符串(如示例代码所示)。

–丹尼斯·威廉姆森
13年7月22日在23:54

是的,当问这个问题时,bash 4还是很新的。

– F. Hauri
13年7月23日在2:31

#5 楼

在许多其他答案中,都有很多极端的情况。但使用uuencode编码Heredoc的内容,如下所示:

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