我试图解析包含潜在100K +线CSV。 这里是我的准则:
- 标识符的索引
- 的标识符值
我想找回在CSV那些在给定索引的给定值(用逗号分隔)的所有行。
任何想法,采取特殊考虑性能?
我试图解析包含潜在100K +线CSV。 这里是我的准则:
我想找回在CSV那些在给定索引的给定值(用逗号分隔)的所有行。
任何想法,采取特殊考虑性能?
使用普通的旧的第一个原型grep
和cut
:
grep ${VALUE} inputfile.csv | cut -d, -f${INDEX}
如果这还不够快,并给出了正确的输出,你就大功告成了。 :)
作为替代cut
-或awk
基础的俏皮话,您可以使用专门的csvtool
又名ocaml-csv
:
$ cat yourfile | csvtool -t ',' col "$index" - | grep "$value"
根据该文档,它处理逃逸,报价等。
看到这个YouTube视频: BASH脚本课10 CSV文件工作
CSV文件:
Bob Brown;Manager;16581;Main
Sally Seaforth;Director;4678;HOME
bash脚本:
#!/bin/bash
OLDIFS=$IFS
IFS=";"
while read user job uid location
do
echo -e "$user \
======================\n\
Role :\t $job\n\
ID :\t $uid\n\
SITE :\t $location\n"
done < $1
IFS=$OLDIFS
输出:
Bob Brown ======================
Role : Manager
ID : 16581
SITE : Main
Sally Seaforth ======================
Role : Director
ID : 4678
SITE : HOME
CSV是没有那么简单。 根据您所拥有的数据的限制,你可能会担心引用值(可能包含逗号和换行符)和转义引号。
所以,如果你的数据只限于足够可以逃脱简单的逗号分割精细,shell脚本可以做到这一点很容易。 如果,另一方面,你需要解析CSV“正常”时,bash不会是我的第一选择。 相反,我想看看在更高层次的脚本语言,例如Python来csv.reader 。
在CSV文件,每个字段由逗号分隔。 问题是,一个字段本身可能有嵌入式逗号:
Name,Phone
"Woo, John",425-555-1212
你真的需要一个库包,提供强大的支持CSV,而不是依靠使用逗号作为字段分隔符。 我知道,脚本语言如Python有这样的支持。 但是,我舒服的Tcl脚本语言,所以这是我使用。 下面是一个简单的Tcl脚本,做你所要求的:
#!/usr/bin/env tclsh
package require csv
package require Tclx
# Parse the command line parameters
lassign $argv fileName columnNumber expectedValue
# Subtract 1 from columnNumber because Tcl's list index starts with a
# zero instead of a one
incr columnNumber -1
for_file line $fileName {
set columns [csv::split $line]
set columnValue [lindex $columns $columnNumber]
if {$columnValue == $expectedValue} {
puts $line
}
}
这个脚本保存到一个文件名为csv.tcl并调用它为:
$ tclsh csv.tcl filename indexNumber expectedValue
该脚本逐行读取CSV文件线和存储在变量$行线,然后把它分割每行成列的列表(变量$列)。 其次,挑选出指定的列,并将其分配给$ columnValue变量。 如果有匹配,打印出原线。
使用awk
:
export INDEX=2
export VALUE=bar
awk -F, '$'$INDEX' ~ /^'$VALUE'$/ {print}' inputfile.csv
编辑:按照丹尼斯·威廉姆森的优秀评论,这可能是更干净(和安全)使用定义变量AWK写-v
开关:
awk -F, -v index=$INDEX -v value=$VALUE '$index == value {print}' inputfile.csv
哎呀...用变量,一切,AWK几乎是一个真正的编程语言 ...
对于其中的数据不包含任何特殊字符的情况下,由内特 - 科尔和ghostdog74提出的解决方案是好的。
如果数据包含字段内逗号或换行符,AWK可能无法正确计算领域的数字,你会得到不正确的结果。
你仍然可以用awk,从一个程序我编写了csvquote(提供一些帮助https://github.com/dbro/csvquote ):
csvquote inputfile.csv | awk -F, -v index=$INDEX -v value=$VALUE '$index == value {print}' | csvquote -u
该程序发现特殊字符引述领域内,并暂时用,不会混淆awk的非打印字符替换它们。 然后AWK完成后,他们得到恢复。
index=1
value=2
awk -F"," -v i=$index -v v=$value '$(i)==v' file
一个sed
或awk
解决方案可能会更短,但这里有一个Perl的:
perl -F/,/ -ane 'print if $F[<INDEX>] eq "<VALUE>"`
其中<INDEX>
是基于0(0为第一列,1表示第二列等)
我一直在寻找一个完美的解决方案,支持引用并且不需要安装任何东西在我的VMware vMA的家电看中。 原来,这个简单的Python脚本的伎俩! (我命名脚本csv2tsv.py
,因为它转换成CSV制表符分隔值- TSV)
#!/usr/bin/env python
import sys, csv
with sys.stdin as f:
reader = csv.reader(f)
for row in reader:
for col in row:
print col+'\t',
print
制表符分隔值可以很容易地与切割命令被分割(没有分隔符需要指定,标签是默认值)。 下面是一个示例使用/输出:
> esxcli -h $VI_HOST --formatter=csv network vswitch standard list |csv2tsv.py|cut -f12
Uplinks
vmnic4,vmnic0,
vmnic5,vmnic1,
vmnic6,vmnic2,
在我的剧本,我真的要通过线来分析TSV输出线和使用读或切割得到我需要的字段。