【问题标题】:Strange behaviour with Bash, Arrays and empty spacesBash、数组和空格的奇怪行为
【发布时间】:2019-02-04 16:36:39
【问题描述】:

问题: 编写一个 bash 脚本,我正在尝试将 csv 文件中的产品列表导入数组:

#!/bin/bash
    PRODUCTS=(`csvprintf -f "/home/test/data/input.csv" -x | grep "col2" | sed 's/<col2>//g' | sed 's/<\/col2>//g' | sed -n '1!p' | sed  '$ d' | sed 's/    //g'`)

    echo ${PRODUCTS[@]}

在交互式 shell 中,结果/输出看起来很完美,如下所示:

burger
special fries
juice - 300ml

当我在 bash 脚本中使用完全相同的命令时,即使使用 bash -x script.sh 进行调试,在 echo ${PRODUCTS[@]} 的部分中,数组的结果是 位于 /home/test/data/ 的所有文件名 和:

burger
special
fries
juice
- 
300ml

该数组正在获取目录列表并弄乱了换行符。这不会发生在交互式 shell(单个命令行)中。 有谁知道如何解决这个问题?

【问题讨论】:

  • 由于你没有引用${PRODUCTS[@]},它会受到分词和全局扩展的影响。不过,不确定-x 有什么不同。
  • 当你说“交互式shell”时,那只是命令的输出(csvprint ... sed ...)吗?
  • 是的,它是在 shell 中输入单行命令时的输出。不在脚本文件中。
  • 我可以看到它在交互式 shell 中以您声称的方式工作的唯一方法是,如果您设置 IFS= 而不记得或告诉我们。

标签: arrays linux bash shell


【解决方案1】:

查看csvprintf 的文档,您正在将 csv 转换为 XML,然后使用正则表达式对其进行解析。这通常是一个非常糟糕的主意。

你可能想安装csvkit 然后你可以这样做

csvcut -c prod input.csv | sed 1d

或者您可以使用 CSV 解析器模块附带的语言。比如红宝石

ruby -rcsv -e 'CSV.read("input.csv", :headers=>true).each {|row| puts row["prod"]}'

无论您使用哪种方法,使用此构造将结果读入 bash 数组

mapfile -t products < <(command to extract the product data)

然后,打印数组元素:

for prod in "${products[@]}"; do echo "$prod"; done
# or
printf "%s\n" "${products[@]}"

数组扩展的引号很关键。如果缺少,您将看到每行一个单词。


提示:不要在 shell 中使用 ALLCAPS 变量名:将这些留给 shell。有一天你会写PATH=something,然后想知道为什么你的脚本坏了。

【讨论】:

    猜你喜欢
    • 2022-11-24
    • 1970-01-01
    • 2018-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多