Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在bash中循环多行CSV行_Bash - Fatal编程技术网

在bash中循环多行CSV行

在bash中循环多行CSV行,bash,Bash,我有以下包含3列的csv文件: row1value1,row1value2,"row1 multi line value" row2value1,row2value2,"row2 multi line value" 是否有一种方法可以循环遍历其行,如(这不起作用,它读取行): 读取$ROW时 做 #一些使用$ROW变量的代码 完成

我有以下包含3列的csv文件:

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中是否可行。