将数组转换为字符串时,无法使IFS正常工作

时间:2012-12-22 02:08:54

标签: linux bash shell

下面是一个bash shell脚本,用于接收csv文件并按照我想要的方式吐出行格式化(有更多更改,但我只保留了下面显示的数组以显示)。

FILENAME=$1
cat $FILENAME | while read LINE
do
    OIFS=$IFS;
    IFS=","
    columns=( $LINE )
    date=${columns[4]//\"/}
    columns[13]=${columns[13]//\"/}
    columns[4]=$(date -d $date +%s)
    newline=${columns[*]}
    echo $newline
    IFS=$OIFS;
done

我正在使用GNU bash v 4.1.2(1) - 发布CentOS 6.3。我尝试过像

这样的引号
newline="${columns[*]}"

仍然没有运气。

以下是样本数据行

112110120001299169,112110119001295978,11,"121.119.163.146.1322221980963094","2012/11/01"

似乎应该将数组输出到逗号分隔的字符串中。相反,字符串是以空格分隔的。有人知道原因吗?

我怀疑它与以下事实有关:如果我在脚本中回显$ IFS它是一个空字符串,但是当我回显“$ {IFS}”时它就是我期望的逗号。

编辑:解决方案

我找到了解决方案。当回显$ newline时,我必须使用它周围的引号,即

echo "$newline"

否则,它使用默认空格。我相信它与bash有关,只有当你用引号强制它时才会为IFS做好准备。

2 个答案:

答案 0 :(得分:2)

我不清楚为什么,但是当使用双引号扩展$ {array [*]}时,bash似乎只使用IFS的第一个字符作为分隔符:

$ columns=(a b "c d e" f)
$ IFS=,
$ echo ${columns[*]}
a b c d e f
$ echo "${columns[*]}"
a,b,c d e,f
$ newline=${columns[*]}; echo "$newline"
a b c d e f
$ newline="${columns[*]}"; echo "$newline"
a,b,c d e,f

幸运的是,解决方案很简单:使用双引号(newline="${columns[*]}"

(顺便说一句,我的测试全部都在bash v3和v2上,因为我没有方便的v4;所以它可能与你不同。)(更新:在bash v4.2.10上测试,结果相同。)

答案 1 :(得分:1)

编辑感谢@GordonDavidson,删除了有关IFS如何在bash中运行的错误评论。

awk有一对非常好的vars,名称FS=","; OFS="|"可以执行此转换。你必须构造awk -F, '{"date -d "$date" +%s" | getline columns[4]}'或类似的来调用外部程序并填充变量。不像shell的c[4]=$(date ...)那么直观,但是awk是一个非常好的工具,可以像你在问题中概述的那样学习数据操作。

这样的东西
#!/bin/awk -f
{
  # columns=( $LINE )
  split($0, columns)

  # date=${columns[4]//\"/}
  myDcolucolumns[4] ; gsub(/\"/, "", myDate)
  # gcolumns[13]=${columns[13]//\"/}
  gsub(/\"/,""columns[13]}
  # columns[4]=$(date -d $date +%s)
  "date -d '"$date"' +%s" | getline columns[4]

  #Don_t_need_this newline=${columns[*]}

  #echo $newline
} print  $0

一样使用
 cat myFile | myAwkScript 

应该达到同样的效果。

很抱歉,但我没有时间,或者现在对样本数据进行测试。 随意回复您收到的错误消息,我会看看我是否可以提供帮助。

您还可以考虑使用1行样本数据和要处理的日期值来更新发布。 IHTH