根据两个标准使用awk过滤

时间:2017-08-25 01:49:25

标签: bash awk

我之前有过类似的问题,但这次我需要更复杂的东西:

在一个如下所示的txt文件中:

147 186741 2S74M -162
83 647172 1S75M -221
163 584665 74M2S 271
99 658416 5S65M6S -272
163 718735 60M16S 243

我希望awk查看第3列,当它在第2或第3位置遇到字符“S”时,它会查看第一列,当遇到“147”或“83”时,它会丢弃那条线。其余的结果传递给第二个awk,它再次查看第3行,当它在结尾遇到字符“S”时,它然后查看第1列,如果它找到“99”或“163”它丢弃了那些线。然后它打印出不符合这些过滤器的其余行。

我尝试了这些方法,但得到了空白文件:

awk -Ft '{if ($3 ~ /S$/  && $1 ~ /99|163/)} {next}' | awk -Ft '{if ($3 ~ /^..?S/ && $1 ~ /147|83/)} {next} $6 ~ /S/ {print}' input.txt > output.txt 

2 个答案:

答案 0 :(得分:0)

首先,6美元可能是一个错字。

现在让我们尝试分步骤。第1步:

awk '$1 ~ /147|83/ && $3 ~ /^..?S/ {next;} {print;}' test.txt

离开我们:

163 584665 74M2S 271
99 658416 5S65M6S -272
163 718735 60M16S 243

如果将这些行放在文件test2.txt中,则应用:

awk '($1 ~ /99|163/ && $3 ~ /S$/) {next;} {print;}' test2.txt

我们没有有效的行,因为所有第3列都有一个' S'最后以99或163开头。

答案 1 :(得分:0)

由于您没有显示正在使用的Input_file,因此我根据您显示的Input_file采用了我的示例,假设以下是您的Input_file。

cat Input_file
147 186741 2S74M -162
83 647172 1S75M -221
163 584665 74M2S 271
99 658416 5S65M6S -272
163 718735 60M16S 243
147 186741 2K74M -162
83 647172 1K75M -221
163 584665 74M2K 271
99 658416 5S65M6K -272
163 718735 60M16S 243

以下是我的代码:

awk '(($1==147 || $1==83) && (substr($3,2,1)=="S" || substr($3,3,1)=="S")) || (substr($3,length($3))=="S" && ($1==99 || $1==163)){next} 1'  Input_file

现在,当我在awk上面运行时,我得到了这些值(我只是为了检查我的代码是否正常而添加),如下所示。

awk '(($1==147 || $1==83) && (substr($3,2,1)=="S" || substr($3,3,1)=="S")) || (substr($3,length($3))=="S" && ($1==99 || $1==163)){next} 1' Input_file
147 186741 2K74M -162
83 647172 1K75M -221
163 584665 74M2K 271
99 658416 5S65M6K -272

所以你可以看到所有那些不在你提供的条件下的行都会被打印出来,给我一些时间也会在这里添加解释。

编辑:此处也添加上述代码的说明,请不要运行此操作,因为我已将其划分为不同的部分,仅供OP理解。

awk '(($1==147 || $1==83)\  ##First condition which re-presents your first awk starts here. checking conditions where $1 value is either 147 OR $1 value is 83
&& \                        ##  AND
(substr($3,2,1)=="S" \      ##substring of 3rd column is EQUAL to letter S
|| \                        ##  OR
substr($3,3,1)=="S"))\      ##substring of 3rd column is EQUAL to letter S
|| \                        ##OR(means either that first aw condition should be TRUE or this following one), the second major condition for which you used second awk I clubbed both the awks into 2 major conditions here.
(substr($3,length($3))=="S"\##checking if substring of column 3s last letter is EQUAL to S here.
&& \                        ##  AND
($1==99 || $1==163)){       ##$1 value is either 99 or 163. So if either of above 2 major conditions are TRUE then perform following statements.
next                        ##next, it is awk keyword which will skip all further statements of line now, without doing any action.
}
1                           ##awk works on method of condition and then action, so here I am making condition as TRUE by mentioning as 1 and NO action is mentioned so be default print action will happen which will print current line.
' Input_file                  ##mentioning Input_file here.
相关问题