我有3列以下csv文件:循環通過多CSV排在bash
row1value1,row1value2,"row1
multi
line
value"
row2value1,row2value2,"row2
multi
line
value"
有沒有辦法通過其行狀循環(這不起作用,它讀取線):
while read $ROW
do
#some code that uses $ROW variable
done < file.csv
我有3列以下csv文件:循環通過多CSV排在bash
row1value1,row1value2,"row1
multi
line
value"
row2value1,row2value2,"row2
multi
line
value"
有沒有辦法通過其行狀循環(這不起作用,它讀取線):
while read $ROW
do
#some code that uses $ROW variable
done < file.csv
使用的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]
然而,正如我評論ABO使用PHP,Perl或Python的專用CSV解析器對於這項工作將更加強大。
這是純粹的bash解決方案。 multiline_csv.sh
腳本通過用一些替換字符串替換引號之間的換行符來將多行csv轉換爲標準csv。所以用法是
./multiline_csv.sh CSVFILE SEP
我把你的示例腳本在名爲./multi.csv
文件。運行命令./multiline_csv.sh ./multi.csv "\n"
產生以下輸出
[[email protected] stackoverflow]$ ./multiline_csv.sh ./multi.csv "\n"
r1c2,r1c2,"row1\nmulti\nline\nvalue"
r2c1,r2c2,"row2\nmultiline\nvalue"
這可以使用printf
很容易地轉換回原來的CSV文件:
[[email protected] stackoverflow]$ printf "$(./multiline_csv.sh ./multi.csv "\n")\n"
r1c2,r1c2,"row1
multi
line
value"
r2c1,r2c2,"row2
multiline
value"
這可能是回聲/的sprintf的具體拱怪癖(我我不確定),但你可以使用其他一些分隔符字符串,如~~~++??//NEWLINE\\??++~~~
,如果需要,你可以輸入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
一旦你完成了這個翻譯,你可以繼續像你通常通過while read $ROW do ... done
方法。
使用PGP,Python,Perl等可用的CVS解析器 – anubhava
我知道有可用的解決方案,但我試圖找出這是否可能在bash中。 –