【问题标题】:How to display file columns containing a specific word using awk如何使用 awk 显示包含特定单词的文件列
【发布时间】:2022-01-10 18:21:37
【问题描述】:

我想打印所有包含单词的列,例如“西瓜”。 A 正在考虑将这两个公式一起使用,因为它们是分开工作的(一个正在为文件中的每一列做一些事情,另一个正在检查列是否包含特定的单词)。

awk '{for(i=1;i<=NF-1;i++) printf $i" "; print $i}' a.csv
awk -F"," '{if ($2 == " watermelon") print $2}' a.csv

但是当我尝试将它们放在一起时,我的代码不起作用

#!/bin/bash 
awk '{for(i=1;i<=NF-1;i++) 
         awk -F"," '{if ($i == " watermelon") 
              print $i}' a.csv    
        }' a.csv

例如这是我的文件 a.csv

lp, type, name, number, letter
1, fruit, watermelon, 6, a
2, fruit, apple, 7, b
3, vegetable, onion, 8, c
4, vegetable, broccoli, 6, b
5, fruit, orange, 5, c

这是我在搜索 word 西瓜时想要得到的结果

name
watermelon
apple
onion
broccoli
orange

【问题讨论】:

  • 请发布一些带有相关预期输出的示例数据。不要将它们作为 cmets、图像、表格或非现场服务的链接发布,而是使用文本并将它们包含在您的原始问题中。谢谢。
  • 好的,我会添加它
  • 如果您在输入的每个逗号后都没有空格,那么请edit您的示例删除这些空格。
  • 其实我有那些空格,有问题吗?
  • 处理起来不是问题,只是文件格式比较奇怪。

标签: linux bash awk script


【解决方案1】:
$ cat tst.awk
BEGIN { FS=OFS=", " }
NR==FNR {
    for (inFldNr=1; inFldNr<=NF; inFldNr++) {
        if ( $inFldNr == tgt ) {
            hits[inFldNr]
        }
    }
    next
}
FNR==1 {
    for (inFldNr=1; inFldNr<=NF; inFldNr++) {
        if ( inFldNr in hits ) {
            out2in[++numOutFlds] = inFldNr
        }
    }
}
{
    for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
        inFldNr = out2in[outFldNr]
        printf "%s%s", $inFldNr, (outFldNr<numOutFlds ? OFS : ORS)
    }
}

$ awk -v tgt='watermelon' -f tst.awk file file
name
watermelon
apple
onion
broccoli
orange

上述和@JamesBrown's approach 之间的主要区别在于,在文件的第二遍中,我的脚本仅循环输出要输出的字段,而 James 循环遍历所有输入字段,因此可能会更慢并非所有输入字段都必须输出的正常情况。

关于 printf $i 在您的代码中顺便说一句 - 永远不要这样做,始终对任何输入数据执行 printf "%s", $i,因为当您的输入包含诸如 %s 之类的 printf 格式化字符时,前者将失败。

【讨论】:

  • 不错的触摸传球目标。
【解决方案2】:

这是一个处理数据两次的方法:

$ awk -F', ' '                          # remember to se OFS if you need one
NR==FNR {                               # on the first run
    for(i=1;i<=NF;i++)                  # find 
        if($i=="watermelon")            # watermelon fields
            a[i]                        # and mark them
    next
}
FNR==1 {                                # in case there were no such field
    for(i in a)                         # test 
        next                            # and continue
    exit                                # or exit
}
{                                       # on the second run
    for(i=1;i<=NF;i++)                 
        if(i in a)b=b (b==""?"":OFS) $i # buffer those fields for output
    print b                             # and output
    b=""                                # clean that buffer for next record
}' file file

输出:

name
watermelon
apple
onion
broccoli
orange

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-12
    • 2014-03-26
    相关资源
    最近更新 更多