【问题标题】:filter multiline record file based if one of the lines meet condition ( word count)根据其中一行是否满足条件(字数)过滤多行记录文件
【发布时间】:2021-07-16 09:55:38
【问题描述】:

大家

我正在寻找一种方法来保存满足以下条件的 txt 文件中的记录:

这是数据的例子:

aa bb cc 
11 22 33 
44 55 66
77 88 99 

aa bb cc 
11 22 33 44 55 66 77
44 55 66 66
77 88 99

aa bb cc 
11 22 33 44 55
44 55 66 
77 88 99 77

...

基本上,它是一个文件,其中一条记录总共有 5 行,4 行包含带有制表符分隔符的字符串/数字,最后是新行 \n。

记录的第一行总是有 3 个元素,而第 2 行第 3 行和第 4 行的元素个数可以不同。

我需要做的是删除每条记录(5行块),其中第二行中的元素总数> 3(我不关心所有其余行中的元素数)。该示例的输出应如下所示:

aa bb cc 
11 22 33 
44 55 66
77 88 99 

...

所以只有我有 3 个元素的记录被保存并记录在新的 txt 文件中。

我尝试通过像这样修改 FS 和 RS 值来使用 awk:

awk 'BEGIN {RS="\n\n"; FS="\n";}
{if(length($2)==3) print $2"\n\n"; }' test_filter.txt

if(length($2)==3) 不正确,因为我应该计算第二个字段中的条目数而不是计算长度,我找不到该怎么做.. 任何帮助都会非常感激!

提前致谢,

【问题讨论】:

    标签: bash if-statement awk


    【解决方案1】:

    您可以使用split() 函数将行/字段/字符串分解为组件;在这种情况下:

    n=split($2,arr," ")
    

    地点:

    • 我们拆分字段 #2,使用单个空格 (" ") 作为分隔符 ...
    • 组件存储在数组arr[] 和...
    • n 是数组中的元素个数

    将其提取到 OP 当前的 awk 代码中,并进行一些小的更改,我们得到:

    awk 'BEGIN {ORS=RS="\n\n"; FS="\n"} {n=split($2,arr," "); if (n>=4) next}1' test_filter.txt
    

    在我们的示例中添加了一个额外的块:

    $ cat test_filter.txt
    aa bb cc
    11 22 33
    44 55 66
    77 88 99
    
    aa bb cc
    11 22 33 44 55 66 77
    44 55 66 66
    77 88 99
    
    aa bb cc
    111 222 333
    444 555 665
    777 888 999
    
    aa bb cc
    11 22 33 44 55
    44 55 66
    77 88 99 77
    

    awk 解决方案生成:

    aa bb cc
    11 22 33
    44 55 66
    77 88 99
    
    aa bb cc
    111 222 333
    444 555 665
    777 888 999
                       # blank line here
    

    【讨论】:

    • ORS=RS="\n\n" 表示它不适用于 POSIX awk,它需要像 GNU awk 这样支持多字符 RS 的 awk。如果您改用RS=""; ORS="\n\n",那么它在任何awk 中的工作方式都相同。您也可以将{n=split($2,arr," "); if (n>=4) next}1' 减少为split($2,a," ")<4
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-21
    • 1970-01-01
    相关资源
    最近更新 更多