在bash中循环多行CSV行
我有以下包含3列的csv文件:在bash中循环多行CSV行,bash,Bash,我有以下包含3列的csv文件: row1value1,row1value2,"row1 multi line value" row2value1,row2value2,"row2 multi line value" 是否有一种方法可以循环遍历其行,如(这不起作用,它读取行): 读取$ROW时 做 #一些使用$ROW变量的代码 完成
row1value1,row1value2,"row1
multi
line
value"
row2value1,row2value2,"row2
multi
line
value"
是否有一种方法可以循环遍历其行,如(这不起作用,它读取行):
读取$ROW时
做
#一些使用$ROW变量的代码
完成
使用gnu awk您可以使用FPAT
:
awk -v RS='"\n' -v FPAT='"[^"]*"|[^,]*' '{
print "Record #", NR, " =======>"
for (i=1; i<=NF; i++) {
sub(/^"/, "", $i)
printf "Field # %d, value=[%s]\n", i, $i
}
}' file.csv
Record # 1 =======>
Field # 1, value=[row1value1]
Field # 2, value=[row1value2]
Field # 3, value=[row1
multi
line
value]
Record # 2 =======>
Field # 1, value=[row2value1]
Field # 2, value=[row2value2]
Field # 3, value=[row2
multi
line
value]
awk-vrs='“\n'-vfpat='”[^”]*“|[^,]*”{
打印“记录”,编号,====>”
对于(i=1;i使用gnu awk,您可以使用FPAT
:
awk -v RS='"\n' -v FPAT='"[^"]*"|[^,]*' '{
print "Record #", NR, " =======>"
for (i=1; i<=NF; i++) {
sub(/^"/, "", $i)
printf "Field # %d, value=[%s]\n", i, $i
}
}' file.csv
Record # 1 =======>
Field # 1, value=[row1value1]
Field # 2, value=[row1value2]
Field # 3, value=[row1
multi
line
value]
Record # 2 =======>
Field # 1, value=[row2value1]
Field # 2, value=[row2value2]
Field # 3, value=[row2
multi
line
value]
awk-vrs='“\n'-vfpat='”[^”]*“|[^,]*”{
打印“记录”,编号,====>”
对于(i=1;i这里是一个纯bash解决方案。multiline_csv.sh
脚本通过用替换字符串替换引号之间的换行符,将多行csv转换为标准csv。因此,用法是
/multiline\u csv.sh CSVFILE SEP
我将您的示例脚本放在一个名为/multi.csv
的文件中。运行命令/multiline\u csv.sh./multi.csv“\n”
生成以下输出
[ericthewry@eric-arch-pc stackoverflow]$ ./multiline_csv.sh ./multi.csv "\n"
r1c2,r1c2,"row1\nmulti\nline\nvalue"
r2c1,r2c2,"row2\nmultiline\nvalue"
可以使用printf
轻松地将其转换回原始csv文件:
[ericthewry@eric-arch-pc stackoverflow]$ printf "$(./multiline_csv.sh ./multi.csv "\n")\n"
r1c2,r1c2,"row1
multi
line
value"
r2c1,r2c2,"row2
multiline
value"
这可能是echo/sprintf的一个主要特性(我不确定),但您可以使用其他一些分隔符字符串,如~~++??//换行\\??+~+~
,如果需要,您可以sed
# multiline_csv.sh
open=0
line_is_open(){
quote="$2"
(printf "$1" | sed -e "s/\(.\)/\1\n/g") | (while read char; do
if [[ "$char" = '"' ]]; then
open=$((($open + 1) % 2))
fi
done && echo $open)
}
cat "$1" | while read ln ; do
flatline="${ln}"
open=$(line_is_open "${ln}" $open)
until [[ "$open" = "0" ]]; do
if read newln
then
flatline="${flatline}$2${newln}"
open=$(line_is_open "${newln}" $open)
else
break
fi
done
echo "${flatline}"
done
完成此翻译后,您可以像往常一样通过读取$ROW do…done
方法继续操作。这里是一个纯bash解决方案。多行csv.sh
脚本通过用替换字符串替换引号之间的换行符将多行csv转换为标准csv。因此,usage是
/multiline\u csv.sh CSVFILE SEP
我将您的示例脚本放在一个名为/multi.csv
的文件中。运行命令/multiline\u csv.sh./multi.csv“\n”
生成以下输出
[ericthewry@eric-arch-pc stackoverflow]$ ./multiline_csv.sh ./multi.csv "\n"
r1c2,r1c2,"row1\nmulti\nline\nvalue"
r2c1,r2c2,"row2\nmultiline\nvalue"
可以使用printf
轻松地将其转换回原始csv文件:
[ericthewry@eric-arch-pc stackoverflow]$ printf "$(./multiline_csv.sh ./multi.csv "\n")\n"
r1c2,r1c2,"row1
multi
line
value"
r2c1,r2c2,"row2
multiline
value"
这可能是echo/sprintf的一个主要特性(我不确定),但您可以使用其他一些分隔符字符串,如~~++??//换行\\??+~+~
,如果需要,您可以sed
# multiline_csv.sh
open=0
line_is_open(){
quote="$2"
(printf "$1" | sed -e "s/\(.\)/\1\n/g") | (while read char; do
if [[ "$char" = '"' ]]; then
open=$((($open + 1) % 2))
fi
done && echo $open)
}
cat "$1" | while read ln ; do
flatline="${ln}"
open=$(line_is_open "${ln}" $open)
until [[ "$open" = "0" ]]; do
if read newln
then
flatline="${flatline}$2${newln}"
open=$(line_is_open "${newln}" $open)
else
break
fi
done
echo "${flatline}"
done
一旦你完成了这个转换,你就可以像平常一样通过读取$ROW do…done
方法继续进行。使用PGP、Python、Perl etcI中可用的CVS解析器知道有可用的解决方案,但我正在试着找出这在bash中是否可行。使用PGP、Python、Perl etcI中可用的CVS解析器知道有可用的解决方案标签解决方案,但我试图找出这在bash中是否可行。