如何提取csv文件的一列

use*_*171 95 csv bash extract

如果我有一个csv文件,是否有快速bash方式打印出任何单个列的内容?可以安全地假设每行具有相同的列数,但每列的内容将具有不同的长度.

syn*_*tel 111

你可以使用awk.将"$ 2"更改为您想要的第n列.

awk -F "\"*,\"*" '{print $2}' textfile.csv
Run Code Online (Sandbox Code Playgroud)

  • `echo'1,"2,3,4,5",6'| awk -F"\"*,\"*"'{print $ 2}'`将打印`2`而不是`2,3,4,5`. (11认同)
  • 我认为当有包含逗号的字符串时会失败,即``,"string,string",...` (7认同)
  • 某些程序返回具有不同分隔符的 CSV 文件,因此可能需要相应地更改正则表达式。分号分隔符示例:`awk -F "\"*;\"*" '{print $2}' textfile.csv` (2认同)

小智 77

是.cat mycsv.csv | cut -d ',' -f3将打印第3列.

  • 除非第二列包含逗号,否则您将获得第二列的后半部分.例如<col1>,"3,000",<col2>.尽管如此,我对这个问题的答案并没有那么好.所以不要被贬低. (6认同)
  • 我们不确定他的 CSV 文件是否包含双引号以区分不同的值。他最好提供一个输入文件,以便我们评估最合适的解决方案。 (2认同)
  • 失败并显示 '1,"a,b,c",3,4' (2认同)

Sam*_*mar 37

我能够完成这项工作的最简单方法就是使用csvtool.我还有其他用例也可以使用csvtool,如果它们出现在列数据本身中,它可以适当地处理引号或分隔符.

csvtool format '%(2)\n' input.csv
Run Code Online (Sandbox Code Playgroud)

用列号替换2将有效地提取您要查找的列数据.

  • 这应该是公认的答案.此工具知道如何处理CSV文件,除了将逗号视为字段分隔符之外.要提取第二列,"csvtool col 2 input.csv" (10认同)
  • 请注意...如果要在标准输入中使用csvtool(示例csv来自另一个命令),则类似于`cat input.csv | csvtool formath'%(2)\ n'-`注意,我知道这里的cat是没有用的,但是对于通常会导出csv的任何命令都可以使用它。 (2认同)

cev*_*ris 13

登陆这里寻找从标签分离文件中提取.以为我会补充一下.

cat textfile.tsv | cut -f2 -s
Run Code Online (Sandbox Code Playgroud)

其中-f2提取2,非零索引列或第二列.

  • 挑剔,但"猫"是不必要的:`<textfile.tsv cut -f2 -s` (5认同)

Str*_*ker 10

这是一个包含 2 列的 csv 文件示例

myTooth.csv
Run Code Online (Sandbox Code Playgroud)
Date,Tooth
2017-01-25,wisdom
2017-02-19,canine
2017-02-24,canine
2017-02-28,wisdom
Run Code Online (Sandbox Code Playgroud)

要获取第一列,请使用:

cut -d, -f1 myTooth.csv
Run Code Online (Sandbox Code Playgroud)

f 代表字段,d 代表分隔符

运行上述命令将产生以下输出。

输出

Date
2017-01-25
2017-02-19
2017-02-24
2017-02-28
Run Code Online (Sandbox Code Playgroud)

仅获取第二列:

cut -d, -f2 myTooth.csv
Run Code Online (Sandbox Code Playgroud)

这是输出 输出

Tooth
wisdom
canine
canine
wisdom
incisor
Run Code Online (Sandbox Code Playgroud)

另一个用例:

您的 csv 输入文件包含 10 列,您需要第 2 到第 5 列和第 8 列,使用逗号作为分隔符”。

cut 使用 -f(意思是“字段”)来指定列,使用 -d(意思是“分隔符”)来指定分隔符。您需要指定后者,因为某些文件可能使用空格、制表符或冒号来分隔列。

cut -f 2-5,8 -d , myvalues.csv
Run Code Online (Sandbox Code Playgroud)

cut 是一个命令实用程序,这里有更多示例:

SYNOPSIS
     cut -b list [-n] [file ...]
     cut -c list [file ...]
     cut -f list [-d delim] [-s] [file ...]
Run Code Online (Sandbox Code Playgroud)


wor*_*ise 8

我认为最简单的是使用csvkit

获取第二列: csvcut -c 2 file.csv

但是,还有csvtool,可能还有许多其他 csv bash 工具:

sudo apt-get install csvtool (对于基于 Debian 的系统)

这将返回一列,其中第一行包含“ID”。 csvtool namedcol ID csv_file.csv

这将返回第四行: csvtool col 4 csv_file.csv

如果要删除标题行:

csvtool col 4 csv_file.csv | sed '1d'


rou*_*ter 6

这个问题的许多答案都很棒,有些人甚至研究过这些问题.我想添加一个简单的答案,可以在日常使用中...你大多数情况下进入那些极端情况(比如在引号中转义逗号或逗号等).

FS(字段分隔符)是一个变量,其值是空间的dafaulted.因此,默认情况下,awk会在空格处为任何行拆分.

所以使用BEGIN(在输入之前执行)我们可以将此字段设置为我们想要的任何内容...

awk 'BEGIN {FS = ","}; {print $3}'
Run Code Online (Sandbox Code Playgroud)

上面的代码将在csv文件中打印第3列.

  • 我已经尝试过了,它仍然考虑引用字段内的逗号。 (2认同)

小智 6

首先,我们将创建一个基本的 CSV

[dumb@one pts]$ cat > file 
a,b,c,d,e,f,g,h,i,k  
1,2,3,4,5,6,7,8,9,10  
a,b,c,d,e,f,g,h,i,k  
1,2,3,4,5,6,7,8,9,10
Run Code Online (Sandbox Code Playgroud)

然后我们得到第一列

[dumb@one pts]$  awk -F , '{print $1}' file  
a  
1  
a  
1
Run Code Online (Sandbox Code Playgroud)


drl*_*sta 5

其他答案运行良好,但由于您只使用bash shell请求解决方案,您可以这样做:

AirBoxOmega:~ d$ cat > file #First we'll create a basic CSV
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
a,b,c,d,e,f,g,h,i,k
1,2,3,4,5,6,7,8,9,10
Run Code Online (Sandbox Code Playgroud)

然后你可以拉出列(本例中的第一列),如下所示:

AirBoxOmega:~ d$ while IFS=, read -a csv_line;do echo "${csv_line[0]}";done < file
a
1
a
1
a
1
a
1
a
1
a
1
Run Code Online (Sandbox Code Playgroud)

所以这里有几件事情:

  • while IFS=, - 这就是说使用逗号作为IFS(内部字段分隔符),这是shell用来知道分隔字段(文本块)的内容.所以说IFS =,就像说"a,b"与"a b"相同,如果IFS =""(默认情况下是这样).

  • read -a csv_line; - 这就是说每行读一次,然后创建一个数组,其中每个元素都被称为"csv_line"并将其发送到while循环的"do"部分

  • do echo "${csv_line[0]}";done < file - 现在我们处于"do"阶段,我们说的是回显数组"csv_line"的第0个元素.在文件的每一行上重复此操作.该< file部分只是告诉while循环从哪里读取.注意:记住,在bash中,数组是0索引的,因此第一列是第0个元素.

所以你有它,从shell中的CSV中拉出一列.其他解决方案可能更实用,但这个是纯粹的bash.


jar*_*rno 5

您可以使用GNU Awk,请参阅用户指南的这篇文章.作为对文章(2015年6月)中提出的解决方案的改进,以下gawk命令允许双引号字段内的双引号; 双引号用两个连续的双引号("")标记.此外,这允许空字段,但即使这样也无法处理多行字段.以下示例打印c=3textfile.csv 的第3列(via ):

#!/bin/bash
gawk -- '
BEGIN{
    FPAT="([^,\"]*)|(\"((\"\")*[^\"]*)*\")"
}
{
    if (substr($c, 1, 1) == "\"") {
        $c = substr($c, 2, length($c) - 2) # Get the text within the two quotes
        gsub("\"\"", "\"", $c)  # Normalize double quotes
    }
    print $c
}
' c=3 < <(dos2unix <textfile.csv)
Run Code Online (Sandbox Code Playgroud)

注意dos2unix用于将可能的DOS样式换行符(CRLF,即"\ r \n")和UTF-16编码(带字节顺序标记)分别转换为"\n"和UTF-8(不带字节顺序标记).标准CSV文件使用CRLF作为换行符,请参阅Wikipedia.

如果输入可能包含多行字段,则可以使用以下脚本.请注意使用特殊字符串来分隔输出中的记录(因为默认分隔符换行符可能出现在记录中).同样,以下示例打印c=3textfile.csv 的第3列(via ):

#!/bin/bash
gawk -- '
BEGIN{
    RS="\0" # Read the whole input file as one record;
    # assume there is no null character in input.
    FS="" # Suppose this setting eases internal splitting work.
    ORS="\n####\n" # Use a special output separator to show borders of a record.
}
{
    nof=patsplit($0, a, /([^,"\n]*)|("(("")*[^"]*)*")/, seps)
    field=0;
    for (i=1; i<=nof; i++){
        field++
        if (field==c) {
            if (substr(a[i], 1, 1) == "\"") {
                a[i] = substr(a[i], 2, length(a[i]) - 2) # Get the text within 
                # the two quotes.
                gsub(/""/, "\"", a[i])  # Normalize double quotes.
            }
            print a[i]
        }
        if (seps[i]!=",") field=0
    }
}
' c=3 < <(dos2unix <textfile.csv)
Run Code Online (Sandbox Code Playgroud)

还有另一种解决问题的方法.csvquote可以输出已修改的CSV文件的内容,以便转换字段中的特殊字符,以便可以使用通常的Unix文本处理工具来选择某个列.例如,以下代码输出第三列:

csvquote textfile.csv | cut -d ',' -f 3 | csvquote -u
Run Code Online (Sandbox Code Playgroud)

csvquote 可用于处理任意大文件.


Dar*_*ous 5

我需要正确的 CSV 解析,而不是cut/awk和祈祷。我正在没有csvtool.

echo "require 'csv'; CSV.read('new.csv').each {|data| puts data[34]}" | ruby
Run Code Online (Sandbox Code Playgroud)


Sou*_*tes 5

我想知道为什么到目前为止没有一个答案提到 csvkit。

csvkit 是一套用于转换和使用 CSV 的命令行工具

csvkit 文档

我专门将它用于 csv 数据管理,到目前为止,我还没有发现使用 cvskit 无法解决的问题。

要从 cvs 文件中提取一列或多列,您可以使用csvcut工具箱中的实用程序。要提取第二列,请使用以下命令:

csvcut -c 2 filename_in.csv > filename_out.csv 
Run Code Online (Sandbox Code Playgroud)

csvcut 参考页

如果 csv 中的字符串带引号,请使用以下q选项添加引号字符:

csvcut -q '"' -c 2 filename_in.csv > filename_out.csv 
Run Code Online (Sandbox Code Playgroud)

使用pip install csvkit或安装sudo apt install csvkit