【问题标题】:Filtering CSV file based on string name根据字符串名称过滤 CSV 文件
【发布时间】:2017-01-07 15:36:00
【问题描述】:

我正在尝试获取 csv 文件的特定列(以防 Header 包含“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 > result.csv

在这种情况下,我尝试将标题中包含“SOF”的列号保存在数组中。之后使用此数字复制列。

【问题讨论】:

  • 请注意,在 awk 中循环遍历数组是这样完成的:for (item in array)。您目前正在使用 Basy 语法。
  • 你完全误解了 awk 的语法和语义。 awk 不是 shell,它是一个完全不同的工具,有自己的语言。获取 Arnold Robbins 的《Effective Awk Programming, 4th Edition》一书,并开始研究前几个示例。
  • 感谢@fedorqui,但仍然无法正常工作:(,我认为我的逻辑是正确的,但结果 csv 为空,并且脚本正在循环运行...
  • 正如@EdMorton 建议的那样,从一个小例子开始,因为您在这里混合了许多基本概念。
  • 关键字containsthenfi不是awk中的关键字。对于contains,您可能需要一个正则表达式和~;其余的只需要从 shell-ish 转换为 Awk。此外,Awk 中的 $i 与 shell 中的 $i 非常不同。

标签: linux bash shell csv awk


【解决方案1】:

初步说明:与从 OP 中包含的代码可能推断出的相反,CSV 中的值用分号分隔。

这是一个包含两个单独命令的解决方案:

  • 第一个解析 CSV 文件的第一行并确定必须导出哪些字段。我为此使用awk
  • 第二个只打印字段。我为此使用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

【讨论】:

  • 我编译脚本时,result.csv 文件的内容与 fil1.csv 相同
  • @LorD 你能echo "$fields"好吗?
  • 使用echo显示变量字段的内容,返回1即可。
  • 文件第一列不包含 SOF
  • @LorD 我使用 gawk 测试了我的解决方案,无论是否使用 POSIX 模式 (--posix),它都有效。你的awk 是什么?
【解决方案2】:

试试这样的...

$ awk 'BEGIN {FS=OFS=","} 
       NR==1 {for(i=1;i<=NF;i++) if($i~/SOF/) {col=i; break}} 
             {print $col}' file

如果找到的标头不存在则不进行处理,因此应打印整行。

【讨论】:

  • 显然,OP 想要选择所有名为“...SOF...”的字段,而不仅仅是一个
【解决方案3】:

This link might be helpful for you :

您可能需要的一个有用命令是“cut”

剪切 -d , -f 2 输入.csv

这里的数字 2 是您要从 csv 文件中删除的列号。

【讨论】:

    【解决方案4】:

    试试这个:

    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] } }'
    

    【讨论】:

    • grep SOF 在第一次出现时不会查找 SOF,因此您可能想用 awk '/$1 ~ "SOF"/{print $0}' 替换它,完整的命令如下所示:awk '{for(i=1;i
    猜你喜欢
    • 2023-03-14
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    • 2017-03-15
    • 2021-03-18
    • 1970-01-01
    相关资源
    最近更新 更多