将CSV值导入Bash

时间:2014-07-15 15:28:37

标签: linux bash csv awk sed

我有以下CSV文件:

more my_file.csv
Alabama,Alaska,Arizona,Arkansas,California,Colorado,Connecticut,Delaware,Florida,Georgia,Hawaii,Idaho,Illinois,Indiana,Iowa
1000,"1 0 0 1",1002,1002,1003,1004,1005,"1 0 0 6",1007,1008,1009,1010,1011,1012,1013
100," 1 0 1 ",102,102,103,104,105,"1 0 6 2",107,108,109,"1 1 0 3 5 62 0",111,112,113
10001,10011,10021,10021,10031,10041,10051,10061,10071,10081,10091,10101,10111,10121,10131
.
.
.
.

我的目标是在我的bash脚本

中设置CSV参数(CSV中的所有状态)及其值

例如(关于第二行值)

在我的bash脚本中,我将能够读取每个参数

例如

 echo $Alabama
 1000 
 echo $Alaska
 1 0 0 1

首先,我尝试编写以下(错误)代码,以便使用其值设置参数:

#!/bin/bash

counter=1

for CSV_COLUMN in Alabama  Alaska  Arizona Arkansas  California  Colorado  Connecticut Delaware Florida  Georgia  Hawaii  Idaho  Illinois  Indiana  Iowa 
do
  export $CSV_COLUMN=` echo $CSV_LINE | cut -d',' -f$counter `
  counter=$counter+1
done

测试应该是(来自bash脚本)

echo $Alabama
1000

我应该如何更改代码才能实现我的想法?

2 个答案:

答案 0 :(得分:6)

解决问题的基本构建块:

#!/bin/bash

while IFS="," read Alabama  Alaska  Arizona Arkansas  California  Colorado  Connecticut Delaware Florida  Georgia  Hawaii  Idaho  Illinois  Indiana  Iowa 
do
    echo $Alabama
done < my_file.csv

根据您的输入文件,这会产生:

sh$ ./m.sh 
Alabama
1000
100
10001

编辑如果您只对第n行感兴趣(存储在CSV_LINE中),则可以sed -n ...p输入文件(并使用if而不是while):

#!/bin/bash

# ...
# Set your CSV_LINE to the (file) line number you are looking for (here, line 2)
CSV_LINE=2
# ...

sed -n "${CSV_LINE}p" | if IFS="," read Alabama  Alaska  Arizona Arkansas  California  Colorado  Connecticut Delaware Florida  Georgia  Hawaii  Idaho  Illinois  Indiana  Iowa 
then
    echo $Alabama
fi < my_file.csv

请注意:由于管道是在子shell 中执行的,因此各种变量仅绑定在内部 {{1声明。


如果您不喜欢if构造,我刚学到的只是使用过程替换,您可能会写:

if

没有管道没有子shell - 因此在发出#!/bin/bash # ... # Set your CSV_LINE to the (file) line number you are looking for (here, line 2) CSV_LINE=2 # ... IFS="," read Alabama Alaska Arizona Arkansas California Colorado Connecticut Delaware Florida Georgia Hawaii Idaho Illinois Indiana Iowa \ < <(sed -n "${CSV_LINE}p" < my_file.csv) echo $Alabama 内部命令后,可以从脚本中的任何位置访问该变量。

答案 1 :(得分:0)

Bash可以处理像您这样的CSV文件(有一些限制,下面有更多内容),其格式如下(假设您运行带有CSV文件作为标准输入的脚本),它使用第一个中的字段名称自动换行为变量名:

# Get the field names from the first line
IFS=, read fields

# Define command to read all fields from a line
fieldsreader="IFS=, read ${fields//,/ }"

# Look over all records
while eval $fieldsreader; do
    ## This is run once per data line
    ## with access to $fieldname for all fields.
done

因此,您的示例可以编码为

IFS=, read fields
fieldsreader="IFS=, read ${fields//,/ }"
while eval $fieldsreader; do
    echo $Alabama
done

将打印

1000
100
10001
...

请注意,使用带有IFS =的bash读取命令,这样就无法正确解析CSV文件:bash只能识别\ _quoting,而不能识别CSV中通常的&#34; -quoting文件(例如,由RFC4180强制执行)。