将 CSV 值导入 Bash
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24762223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Import CSV value into Bash
提问by maihabunash
I have the following CSV file:
我有以下 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
.
.
.
.
My target is to set the CSV parameters ( all states in CSV ) with their values in my bash script
我的目标是在我的 bash 脚本中使用它们的值设置 CSV 参数(CSV 中的所有状态)
for example( regarding the second line values )
例如(关于第二行值)
in my bash script I will able to read each parameter
在我的 bash 脚本中,我将能够读取每个参数
example
例子
echo $Alabama
1000
echo $Alaska
1 0 0 1
First I just tried to write the following (wrong) code, in order to set the parameters with their values:
首先,我只是尝试编写以下(错误的)代码,以便使用它们的值设置参数:
#!/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
The test should be (from the bash script)
测试应该是(来自 bash 脚本)
echo $Alabama
1000
How should I change my code in order to implement my idea?
我应该如何更改代码以实现我的想法?
回答by Sylvain Leroux
Basic building block to solve your problem:
解决您的问题的基本构建块:
#!/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
Given your input file, this produces:
给定您的输入文件,这会产生:
sh$ ./m.sh
Alabama
1000
100
10001
EDITIf you are only interested in the n-th line (stored in CSV_LINE
), you could sed -n ...p
your input file (and use if
instead of while
):
编辑如果您只对第 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
Please note: since pipesare executed in a sub shell, the various variables are only bound insidethe body of the if
statement.
请注意:由于管道在子 shell中执行,因此各种变量仅绑定在if
语句主体内。
If you don't like the if
construct, I've just learned than using process substitution you might write:
如果你不喜欢这个if
结构,我刚刚学到的不是使用过程替换,你可能会写:
#!/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
Without a pipethere is not sub-shell -- so the variable are accessible from anywhere in the script after issuing the read
internal command.
没有管道就没有子外壳——因此在发出read
内部命令后,可以从脚本中的任何地方访问该变量。
回答by krisrose
Bash can handle CSV files like yours (there are some restrictions, more on that below) with a pattern like the following (assuming you run the script with the CSV file as standard input), which uses the field names in the first line as variable names automatically:
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
Your example could thus be encoded as
因此,您的示例可以编码为
IFS=, read fields
fieldsreader="IFS=, read ${fields//,/ }"
while eval $fieldsreader; do
echo $Alabama
done
which will print
这将打印
1000
100
10001
...
Notice, however, that using bash's read command with IFS=, in this way does not parse CSV files properly: bash only recognizes \-quoting but not the "-quoting that is usual in CSV files (as mandated, for example, by RFC4180).
但是请注意,使用带有 IFS= 的 bash 的读取命令,以这种方式不能正确解析 CSV 文件:bash 仅识别 \-quoting 而不是 CSV 文件中常见的“-quoting(例如,由RFC4180强制要求))。