【问题标题】:AWK removal of lines in CSV with two empty fields?AWK 删除 CSV 中带有两个空字段的行?
【发布时间】:2015-04-30 19:15:58
【问题描述】:

我很少使用 awk,我想我忘记了将它与 CSV 文件一起使用的基本知识,在这里,但我有以下文件,名为 new2.csv:

Filename,Dist.(ft),BR Name,BR 2-Way Time,Till/WBR Name,Till/WBR 2-Way Time
FILE____007P_1.DZT,0,BR,,Till/WBR,
FILE____007P_1.DZT,0.042,BR,,Till/WBR,
FILE____007P_1.DZT,0.083,BR,,Till/WBR,
FILE____007P_1.DZT,0.125,BR,,Till/WBR,
FILE____007P_1.DZT,0.167,BR,,Till/WBR,
FILE____007P_1.DZT,0.208,BR,92.58,Till/WBR,
FILE____007P_1.DZT,0.25,BR,,Till/WBR,29.3
FILE____007P_1.DZT,0.292,BR,,Till/WBR,

我只想使用 awk 保留第四列或第六列(第 7 行和第 8 行)中具有值的行。

我尝试了一些方法来检查那里发生了什么:

awk -F',' '{print NR, "->", $4}' new2.csv

返回第 7 行 -> 第 7 行返回 92.58,其余行返回任何内容,这很好。接下来,我尝试了

awk -F',' '{print NR, "->", $6}' new2.csv

返回第 8 行 -> 29.3,所以我们仍然很好。

认为我已经解决了,我继续前进

awk -F',' '$4!=""' new2.csv

并按预期打印标题行和代码的第七行。继续第 6 列,我编写了相同的表达式,它返回 new2.csv 的全部内容。为了解决问题,我尝试了

awk -F',' '{print NR, "->", $6!=""}' new2.csv

然后返回第 1 行 -> 1, 第 2 行 -> 1, ..., 第 8 行 ->1, ...等等,所以这是我的问题。这是怎么回事?有什么办法可以解决吗?

行尾的逗号似乎可能是问题的根源,但在阅读了很多帖子后,我仍然不确定该怎么做。 awk '{print substr($0,0,length($0)-1)}' new.csv 也不会删除最后一个逗号。我在 Windows 8 机器上生成了 csv,并在 bash 中的 Linux 机器上使用 awk。

【问题讨论】:

  • 第 4 列和第 6 列都有值?
  • 您的示例输入没有在第 4 列和第 6 列中具有值的行。 FILE____007P_1.DZT,0.208,BR,92.58,Till/WBR, 在第 4 列有 92.58,但在第 6 列没有,而FILE____007P_1.DZT,0.25,BR,,Till/WBR,29.3 在第 6 列有 29.3,但在第 4 列没有,其他任何地方都没有值。
  • 是的,数据集中的所有行都有 $1、$2、$3 和 $5 的值。有些行也有 $4 或 $6 值,但没有行(除了标题)将同时具有 $4 && $6 值。最终目标是编写一个新文件,该文件仅包含在第四列或第六列中具有值的行。刚刚在上面进行了编辑以澄清 - 感谢您抓住它。
  • 好的,然后将您问题中的所有“和”更改为“或”。新文件是否应该包含标题行?

标签: bash csv awk


【解决方案1】:
$ awk -F, '($4$6)~/./' file
Filename,Dist.(ft),BR Name,BR 2-Way Time,Till/WBR Name,Till/WBR 2-Way Time
FILE____007P_1.DZT,0.208,BR,92.58,Till/WBR,
FILE____007P_1.DZT,0.25,BR,,Till/WBR,29.3

或者如果您希望仅包含空格的字段也被视为“空”:

$ awk -F, '($4$6)~/[^[:space:]]/' file
Filename,Dist.(ft),BR Name,BR 2-Way Time,Till/WBR Name,Till/WBR 2-Way Time
FILE____007P_1.DZT,0.208,BR,92.58,Till/WBR,
FILE____007P_1.DZT,0.25,BR,,Till/WBR,29.3

如果你想排除标题行:

$ awk -F, '(NR>1) && (($4$6)~/[^[:space:]]/)' file
FILE____007P_1.DZT,0.208,BR,92.58,Till/WBR,
FILE____007P_1.DZT,0.25,BR,,Till/WBR,29.3

【讨论】:

  • 你能解释一下[^[:space:]]吗? +1 简单明了的答案!
  • [:space:] 是一个 POSIX 字符类,表示任何空格字符(空白、制表符、换页符、换行符等),因此 [^[:space:]] 是一个 POSIX 括号表达式,表示 not a space
【解决方案2】:
Filename,Dist.(ft),BR Name,BR 2-Way Time,Till/WBR Name,Till/WBR 2-Way Time FILE____007P_1.DZT,0,BR,,Till/WBR,
FILE____007P_1.DZT,0.042,BR,,Till/WBR,
FILE____007P_1.DZT,0.083,BR,,Till/WBR,
FILE____007P_1.DZT,0.125,BR,,Till/WBR,
FILE____007P_1.DZT,0.167,BR,,Till/WBR,
FILE____007P_1.DZT,0.208,BR,92.58,Till/WBR,
FILE____007P_1.DZT,0.25,BR,,Till/WBR,29.3
FILE____007P_1.DZT,0.292,BR,,Till/WBR,

hzhang@dell-work ~ $ cat test.awk 
#!/usr/bin/awk
BEGIN{
    FS = ","
}
{
    # ignore the first definition line
    if(FNR > 1){
        # checks column 4 has a non-empty value
        if($4 !=""){
            print FNR,"->", $4
        }

        # checks column 6 has a non-empty value
        if($6 != ""){
            print FNR,"->", $6
        }

    }
}
hzhang@dell-work ~ $ awk -f test.awk sample.csv 
6 -> 92.58
7 -> 29.3

如果你想在控制台上运行命令行:

hzhang@dell-work ~ $ awk -F, '(FNR>1){if($4 != ""){ print FNR,"->",$4  }; if($6 != ""){ print FNR,"->",$6  }}' sample.csv 
6 -> 92.58
7 -> 29.3

【讨论】:

  • 这行得通,虽然我不明白为什么它不会遇到与awk -F',' '{print NR, "->", $6!=""}' new2.csv 行相同的问题?非常感谢!
【解决方案3】:

你正在混淆模式和动作。

awk -F',' '$4!=""' 是一个没有动作的模式,它说“如果$4 为空,则执行默认值”。默认操作是打印输入。

awk -F',' '{print NR, "->", $6!=""}' 是一个没有模式的动作。缺少模式会使操作的所有行匹配。它说 -- 打印行号,然后是 ->,然后是比较 $6 和“空”的结果(这是一个布尔值 0 或 1,1 表示“真”)。

要做你想做的事,你可以使用裸模式:

awk -F, '$4!="" || $6!=""'

这表示-“$4 的默认操作不为空,或者$6 不为空”。默认操作是打印输入。

或者您可以使用裸操作:

awk -F, '{ if ($4 != "" || $6 != "") { print $0; } }'

这句话说——如果$4 不为空,或者$6 不为空,则打印$0(这是输入行)。

附:从您的问题和行动来看,尚不清楚您是否想要第 4 行和第 6 行都不是空的,或者只有一个。如果两者都是,那么关于的测试应该是 and (&&) 而不是 or (||)

【讨论】:

  • 嗨 Pawel,我从包含您指出的 OR 语句的裸模式开始。一旦我注意到它返回了所有行,我决定将每行的结果打印到屏幕上,以了解发生了什么。 awk -F',' '$4!=""' 的输出是第 7 行,正如预期的那样,但awk -F',' '$6!=""' 的输出返回所有行,而不仅仅是第 8 行。对不起,我的下一步是,一旦我成功设计了一行代码当我查看 $6 时,它只产生第 8 行,肯定会涉及 ||我会将结果打印到一个新文件中。
  • @k.mat27 如果$6!="" 打印所有行,则其他行的末尾有尾随空格。请改用$6~/[^[:space:]]/
猜你喜欢
  • 2017-07-11
  • 2013-07-14
  • 1970-01-01
  • 2012-05-08
  • 2010-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
相关资源
最近更新 更多