Linux 基于字符串名筛选CSV文件
我正在尝试获取csv文件的特定列(在这种情况下,该标题包含“SOF”)。是一个大文件,我需要使用Shell将此列复制到另一个csv文件 我试过这样的方法:Linux 基于字符串名筛选CSV文件,linux,bash,shell,csv,awk,Linux,Bash,Shell,Csv,Awk,我正在尝试获取csv文件的特定列(在这种情况下,该标题包含“SOF”)。是一个大文件,我需要使用Shell将此列复制到另一个csv文件 我试过这样的方法: #!/bin/bash awk ' { i=1 j=1 while ( NR==1 ) if ( "$i" ~ /SOF/ ) then array[j] = $i $j += 1 fi $i += 1 for ( k in array ) print array[k] }' fil1.csv > re
#!/bin/bash
awk ' {
i=1
j=1
while ( NR==1 )
if ( "$i" ~ /SOF/ )
then
array[j] = $i
$j += 1
fi
$i += 1
for ( k in array )
print array[k]
}' fil1.csv > result.csv
在本例中,我尝试将标题中包含“SOF”的列号保存到数组中。然后,用这些数字复制列。试试这样的方法
$ awk 'BEGIN {FS=OFS=","}
NR==1 {for(i=1;i<=NF;i++) if($i~/SOF/) {col=i; break}}
{print $col}' file
$awk'开始{FS=OFS=“,”}
NR==1{(i=1;i初步说明:与从OP中包含的代码推断的相反,CSV中的值用分号分隔
下面是一个包含两个单独命令的解决方案:
- 第一个解析CSV文件的第一行,并确定必须导出哪些字段
- 第二个只打印字段。我使用
cut
进行此操作(语法比awk
更简单,速度更快,尤其是当文件较大时)
其思想是,第一个命令生成字段编号列表,以“,”分隔,适合作为参数传递给cut
:
# Command #1: identify fields
fields=$(awk -F";" '
{
for (i = 1; i <= NF; i++)
if ($i ~ /SOF/) {
fields = fields sep i
sep = ","
}
print fields
exit
}' fil1.csv
)
# Command #2: export fields
{ [ -n "$fields" ] && cut -d";" -f "$fields" fil1.csv; } > result.csv
#命令#1:识别字段
字段=$(awk-F);“'
{
对于(i=1;i
您可能需要的有用命令之一是“剪切”
cut-d,-f2 input.csv
这里的数字2是您要从csv文件中剪切的列号。试试这个:
awk '{for(i=1;i<=NF;i++)a[i]=a[i]" "$i}END{for (i in a ){ print a[i] } }' filename | grep SOF | awk '{for(i=1;i<=NF;i++)a[i]=a[i]" "$i}END{for (i in a ){ print a[i] } }'
awk'{for(i=1;inote)在awk中循环数组是这样做的:for(数组中的项)
。您当前使用的是Basy语法。您完全误解了awk语法和语义。awk不是shell,它是一个完全不同的工具,有自己的语言。请阅读Arnold Robbins的《有效的awk编程,第四版》,并开始学习前几个示例。谢谢@fedorqui,但仍然不起作用惯性导航与制导:(,我认为我的逻辑是正确的,但结果csv是空的,脚本在循环中运行…正如@EdMorton所建议的,从一个小例子开始,因为您在这里混合了许多基本概念。关键字包含,然后和fi
不是awk
中的关键字。您可能需要一个正则表达式和de>for包含
;其余的只需要从shell ish转换为Awk。此外,Awk中的
$i
与shell中的
$i
非常不同。显然,OP希望选择所有名为“…SOF…”的字段,而不仅仅是其中一个。当我编译script@LorD你能echo吗“$fields”
please?使用echo显示变量字段的内容,只需返回1。文件的第一列不包含SOF@LorD我用gawk
测试了我的解决方案,有没有POSIX模式(--POSIX
)你的awk
是什么?grep-SOF在第一次出现时不寻找SOF,所以你可能想用awk'/$1~“SOF”/{print$0}替换它,完整的命令变成这样:awk'{for(i=1;i