的Bash shell脚本 - CSV解析(Bash shell scripting - csv

2019-07-23 02:38发布

我试图解析包含潜在100K +线CSV。 这里是我的准则:

  1. 标识符的索引
  2. 的标识符值

我想找回在CSV那些在给定索引的给定值(用逗号分隔)的所有行。

任何想法,采取特殊考虑性能?

Answer 1:

使用普通的旧的第一个原型grepcut

grep ${VALUE} inputfile.csv | cut -d, -f${INDEX}

如果这还不够快,并给出了正确的输出,你就大功告成了。 :)



Answer 2:

作为替代cut -或awk基础的俏皮话,您可以使用专门的csvtool又名ocaml-csv

$ cat yourfile | csvtool -t ',' col "$index" - | grep "$value"

根据该文档,它处理逃逸,报价等。



Answer 3:

看到这个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


Answer 4:

CSV是没有那么简单。 根据您所拥有的数据的限制,你可能会担心引用值(可能包含逗号和换行符)和转义引号。

所以,如果你的数据只限于足够可以逃脱简单的逗号分割精细,shell脚本可以做到这一点很容易。 如果,另一方面,你需要解析CSV“正常”时,bash不会是我的第一选择。 相反,我想看看在更高层次的脚本语言,例如Python来csv.reader 。



Answer 5:

在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变量。 如果有匹配,打印出原线。



Answer 6:

使用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几乎是一个真正的编程语言 ...



Answer 7:

对于其中的数据不包含任何特殊字符的情况下,由内特 - 科尔和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完成后,他们得到恢复。



Answer 8:

index=1
value=2
awk -F"," -v i=$index -v v=$value '$(i)==v' file


Answer 9:

一个sedawk解决方案可能会更短,但这里有一个Perl的:

perl -F/,/ -ane 'print if $F[<INDEX>] eq "<VALUE>"`

其中<INDEX>是基于0(0为第一列,1表示第二列等)



Answer 10:

我一直在寻找一个完美的解决方案,支持引用并且不需要安装任何东西在我的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输出线和使用读或切割得到我需要的字段。



文章来源: Bash shell scripting - csv parsing
标签: bash csv shell