如何在bash中迭代多行变量?

4

鉴于

# this is programmatically generated... hard-coded here for this example
commands="\nthing1@this is thing 1!\nthing2@this is thing 2!"

while read -r line; do
  cmd=$(printf "$line" | cut -d'@' -f1 | tr -d '\n')
  desc=$(printf "$line" | cut -d'@' -f2 | tr -d '\n')

  printf '  %-20s %s\n' "$cmd" "$desc"
done <<< "$commands"

我预期会输出以下内容。
  thing1        this is thing1!
  thing2        this is thing2!

相反,我得到了:
  thing1thing2        this is thing1!this is thing2!

我做错了什么?

我想要读取换行符,以便可以在@处进行剪切格式化输出


1
怎么样用 echo "$commands" | awk -F@ '{printf("%20s\t%s\n",$1, $2)}' 一次处理所有数据,而不是每行 ~8 个进程 ;-)。祝你好运。 - shellter
啊,我觉得应该是 echo -e ...但是,没想到会用到 awk。我不是 bash 大师,所以对于每行进程的滥用表示歉意。 :-o 你介意把你的解决方案发表为答案吗? - neezer
1
你是使用两个字符序列 \\n 还是真正的换行符来自动生成字符串? - rici
通常情况下,几乎没有理由像这样使用 cut。让 read 带着 while IFS=@ read -r cmd desc _; do ... 为您解析即可。 - William Pursell
@neezer:这并没有回答我的问题:) 在你的示例代码中,两个字符序列 \\ n 不是 换行符,因此 read -r 会将整个字符串读取为一行(它本来就是一行)。这个事实,加上你的示例由于使用未转义的感叹号而无法正常工作,让我想知道你是否真的意味着那些要成为换行符。 - rici
显示剩余2条评论
2个回答

1
#!/bin/bash

input="\nthing1@this is thing 1!\nthing2@this is thing 2!"

# echo replaces '\n's with real new-lines
# readarray -t loads the multiline string into an array
readarray -t array <<< $(echo -e "${input}")

# loop it
for command in "${array[@]}"; do
    echo "${command}"
done

你如何避免出现“-bash:!\nthing2@this:event not found”错误? - David C. Rankin
哇,我不明白。发布了整个脚本。 - hedgar2017
没有对 input 进行单引号包裹,那么 ! 就不被允许。 (这可能是问题本身的打字错误)只需尝试 input="\nthing1@this is thing 1!\nthing2@this is thing 2!"; echo -e "$input" 然后再用 单引号 包裹它并再次尝试。 - David C. Rankin
! 不是特殊符号。 我单引号了,什么都没变,因为这不重要。 你使用的Bash版本是什么? - hedgar2017
1
bash 4.4开始,您可以使用${input@E}代替$(echo -e "$input") - chepner
显示剩余9条评论

0
根据您的问题,似乎当使用here strings时,bash不会解释任何\n \t \f等。这可能是您想要的,但也可能是不好的实践。双引号周围加上感叹号将导致错误,因为bash将尝试将其评估为事件(在某个时间点在shell上执行的命令),因此您必须对其进行转义(在终端上使用时)。
commands="\nthing1@this is thing 1\!\nthing2@this is thing 2!"

while read line;do
   // do your stuff here
line <<< $( echo -e "${commands}" )  # -e switch tells the echo command to honour all back slashes . The same behaviour can be achieved with `shopt -s xpg_echo` ( you have to remove -e switch whenever you do that )

噪音:注意:当从终端使用时:如果你仔细看命令变量,我没有在"!" 前加反斜杠,这是因为它没有任何值作为前缀,所以 bash 不会尝试将前面的值作为事件进行定位。

如果需要更多相关信息,请查阅 Bash man 页面中的历史扩展部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接