根据列内的字符串匹配数删除列

Gil*_*les 5 awk text-processing

我需要一个命令来删除文本文件中的任何列,如果它们在列(具有不同行数的列)中有 =>${MaxAllowedNumberOfFs} 'F's 。

我有一些接近的伪代码,但我不知道如何设置匹配数限制器。

假设限制器设置为 3,示例输入文件是:

F G F H H
G F F F A
F G F F F
F F F T F
Run Code Online (Sandbox Code Playgroud)

那么所需的输出将是:

G H H
F F A
G F F
F T F
Run Code Online (Sandbox Code Playgroud)

接近的伪代码(限制器可以并且会根据文件而改变):

MaxAllowedNumberOfFs="1012"

Count_of_columns=`awk '{print NF}' filename | sort -nr | sed -n '$p'` 

for((i=1;i<=$Count_of_columns;i++)); do awk -v i="$i" -v x="$MaxAllowedNumberOfFs" '$i == F =>x number of times {$i="";print $0}' filename; done
Run Code Online (Sandbox Code Playgroud)

显然,我可以使用 grep 遍历所有列,计算列中出现的次数,然后删除不符合条件的列。但这真的很慢。真的想要一个漂亮的 awk 命令,但我没有 awk 技能

ica*_*rus 3

一种方法是读取文件两次。第一次计算 F,第二次输出该行。所以像

#!/bin/sh

awk -v n=3 '
        NR==FNR { for (i=1;i<=NF;i++) { if ($i == "F") { c[i]++ }} ;next }                                                                            
        { for (i=1;i<=NF;i++) { if (c[i] < n) { printf("%s ", $i) } } ;printf("\n") }                                                                 

' filename filename
Run Code Online (Sandbox Code Playgroud)

NR==FNR是一个技巧来判断这是我们第一次还是第二次读取文件。假设文件中有任何行,那么仅在第一次读取文件时才为真。该数组c是该列中 F 字符数的计数。表示next该行的所有处理在第一次读取文件时已完成。第二行在第二次读取文件时执行。