下面是一个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做好准备。
答案 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