【问题标题】:awk keep header when using IGNORECASE使用 IGNORECASE 时 awk 保留标题
【发布时间】:2019-09-22 06:20:44
【问题描述】:

我有一个 csv 文件,我想在特定列 columnB(我的数据集中的第 5 列)中搜索一个字符串(忽略大小写),并在另一个columnC(我的数据集中的第 10 列)上应用过滤器.然后将选定的列保存到文件中。

数据集样本

columnA     columnB    columnC  columnD
abc          Apple      100     today
nbd          apple      50      tomorrow
ccc          apple      101     today

想要的输出

columnB    columnC
Apple      100
apple      101

我使用awk时的问题我可以选择columnB,但我无法输出标题。

 awk 'BEGIN {IGNORECASE = 1} {if($5 == "Apple") print $0 }' Data.csv> testPipe.txt

我尝试过使用NR==1,但由于某种原因它不适用于IGNORECASE

我也试过herehere的方法。

我尝试使用grip,我可以输出标题但我无法指定columnB 用于字符串匹配。搜索将应用于所有列。

cat Data.csv |{ head -1; grep -I "Apple";} | awk -F',' '{ if ($10 >100 ) { print } }'>testPipe.txt

有没有办法结合这两种方法并获得所需的输出? 谢谢

【问题讨论】:

  • Wrt 我尝试过使用 NR==1,但由于某种原因它不适用于 IGNORECASE。,您尝试过 NR==1{print;next} 吗?它在这里工作正常
  • 你建议我在哪里添加这一行?在if条件下? awk 'BEGIN {IGNORECASE = 1} {if($5 == "Apple") NR==1{print;next}}' Data.csv> testPipe.txt
  • 这是一个条件-动作对,放在BEGIN规则之后。喜欢awk 'BEGIN {IGNORECASE = 1} NR==1{print;next} $5 == "Apple"' Data.csv> testPipe.txt
  • awk 'BEGIN {IGNORECASE = 1} NR==1{print;next} 5 == "Apple" && $10>100' FData.csv> testPipeNew.csv 它只返回标题。有空列
  • 不正常吗?因为 5 永远不等于“Apple”????你在那里缺少$

标签: bash awk ignore-case


【解决方案1】:

使用函数tolower()

awk 'NR==1{print; next} tolower($5) == "apple"' file

解释:

# Print the headers
NR==1 {
    print
    next
}

# Print the current line if $5 matches the condition
# Note that if there is no action specified, awk will
# use print $0 by default
tolower($5)

如果您想在条件为真的情况下编写进一步的操作,请将它们放入一个块中

tolower($5) {
    ...
}

与仅适用于 GNU awk 的 IGNORECASE 相反,tolower() 将适用于任何版本的 awk,因为它是由 POSIX 定义的。

【讨论】:

  • 谢谢,你知道它会转换最终结果吗?
  • 你可以试试
  • 它适用于匹配部分,它不会改变大小写。是否可以添加另一个条件,当我这样做时它不会删除空值。我可能在这里做错了什么。 awk 'NR==1{print;next} tolower($5)=="apple" && $5 !="NULL"' FData.csv>match.csv
  • @leena 当您对各种答案的 cmets 提出更多要求时,这会非常令人困惑。请不要那样做。而是使用具有相关预期输出的更新数据样本更新原始问题,或者提出一个新问题。
  • 打印它们有什么问题?
【解决方案2】:

更新:显然我的回答没有我想象的那么好,请参阅下面 Ed Morton 的评论。无论如何,我会保留它,作为“如何不做”。

原始(错误)答案:

在设置 IGNORECASE 之前或之后将以下内容添加到您的 BEGIN 子句中:

getline;
print;

说明:BEGIN 子句在其他所有操作之前执行一次,因此您也可以在那里处理行,但您必须手动读取它们。

完整示例:

awk '
    BEGIN {
        getline;
        print;
        IGNORECASE = 1;
    }

    $2 == "apple" && $3 <= 100 {
        print $1;
    }
'

【讨论】:

  • 这样吗? awk 'BEGIN getline; print; {IGNORECASE = 1} {if($5 == "Apple") print $0 }' FData.csv&gt;2222.csv 抱歉,我是 Bash 的初学者。期待您的澄清。谢谢
  • 谢谢,它运行良好。我只需要将 1 更改为 0。他们是在 print 语句中选择特定列的一种方式吗?例如{print $4,$5,$10},如果我想将结果保存在文本文件中,是否需要修改代码?谢谢
  • 我再次运行了代码。有些行不符合条件:(知道为什么会这样吗?
  • 您不需要/不想为此使用 getline。见awk.freeshell.org/AllAboutGetline
  • @EdMorton,谢谢你的启发,我加了评论
猜你喜欢
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-15
  • 2018-02-22
  • 1970-01-01
  • 2013-10-09
相关资源
最近更新 更多