我正在尝试解析包含可能100k +行的CSV.这是我的标准:
我想检索CSV中具有给定索引中给定值的所有行(用逗号分隔).
任何想法,特别考虑性能?
And*_*ikh 46
作为cut- 或awk基于单行的替代方案,您可以使用专门的csvtoolaka ocaml-csv:
$ cat yourfile | csvtool -t ',' col "$index" - | grep "$value"
Run Code Online (Sandbox Code Playgroud)
根据文档,它处理转义,引用等.
小智 42
请参阅此youtube视频:使用CSV文件的BASH脚本课程10
CSV文件:
Bob Brown;Manager;16581;Main
Sally Seaforth;Director;4678;HOME
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
输出:
Bob Brown ======================
Role : Manager
ID : 16581
SITE : Main
Sally Seaforth ======================
Role : Director
ID : 4678
SITE : HOME
Run Code Online (Sandbox Code Playgroud)
unw*_*ind 28
第一个原型使用普通旧grep和cut:
grep ${VALUE} inputfile.csv | cut -d, -f${INDEX}
Run Code Online (Sandbox Code Playgroud)
如果它足够快并且提供适当的输出,那么你就完成了.:)
bob*_*nce 12
CSV并不那么简单.根据您拥有的数据限制,您可能不得不担心引用的值(可能包含逗号和换行符)和转义引号.
因此,如果您的数据受到足够的限制,可以通过简单的逗号分割来解决问题,那么shell脚本可以轻松实现.另一方面,如果你需要正确解析CSV,那么bash不是我的首选.相反,我会看一个更高级别的脚本语言,例如带有csv.reader的 Python .
在CSV文件中,每个字段用逗号分隔.问题是,字段本身可能有一个嵌入的逗号:
Name,Phone
"Woo, John",425-555-1212
Run Code Online (Sandbox Code Playgroud)
您确实需要一个提供强大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
}
}
Run Code Online (Sandbox Code Playgroud)
将此脚本保存到名为csv.tcl的文件中,并将其调用为:
$ tclsh csv.tcl filename indexNumber expectedValue
Run Code Online (Sandbox Code Playgroud)
该脚本逐行读取CSV文件并将该行存储在变量$ line中,然后将每行拆分为列列(变量$ columns).接下来,它选择指定的列并将其分配给$ columnValue变量.如果匹配,请打印出原始行.
使用awk:
export INDEX=2
export VALUE=bar
awk -F, '$'$INDEX' ~ /^'$VALUE'$/ {print}' inputfile.csv
Run Code Online (Sandbox Code Playgroud)
编辑:根据Dennis Williamson的优秀评论,通过使用-v开关定义awk变量,可以更清晰(和安全)地编写:
awk -F, -v index=$INDEX -v value=$VALUE '$index == value {print}' inputfile.csv
Run Code Online (Sandbox Code Playgroud)
Jeez ......有变量和一切,awk几乎是一种真正的编程语言 ......
对于数据不包含任何特殊字符的情况,Nate Kohl 和 ghostdog74 建议的解决方案是好的。
如果数据在字段中包含逗号或换行符,awk 可能无法正确计算字段编号,并且您会得到不正确的结果。
在我编写的名为 csvquote 的程序(可在https://github.com/dbro/csvquote 上找到)的帮助下,您仍然可以使用 awk :
csvquote inputfile.csv | awk -F, -v index=$INDEX -v value=$VALUE '$index == value {print}' | csvquote -u
Run Code Online (Sandbox Code Playgroud)
该程序在带引号的字段中查找特殊字符,并临时用不会混淆 awk 的非打印字符替换它们。然后他们在 awk 完成后恢复。
| 归档时间: |
|
| 查看次数: |
112579 次 |
| 最近记录: |