Bash AWK中的条件

Bash AWK中的条件,bash,awk,conditional-statements,Bash,Awk,Conditional Statements,我正在使用awk(版本20070501,在MacOS上)过滤一些数据,但在对特定列中的值应用多个负匹配条件时遇到语法挑战 这里有一个通用的例子,我认为它抓住了我的问题 输入: foo,bar bar,foo foo,bar bar,foo 使用此代码,我将删除第2列中foo的匹配项: awk'BEGIN{FS=OFS=“,”};{if($2!~/foo/)打印$0}' 我得到了这个输出,我期望: foo,bar foo,bar 接下来,我在if语句中添加一个附加条件,以删除第2列中与bar匹

我正在使用
awk
(版本20070501,在MacOS上)过滤一些数据,但在对特定列中的值应用多个负匹配条件时遇到语法挑战

这里有一个通用的例子,我认为它抓住了我的问题

输入:

foo,bar
bar,foo
foo,bar
bar,foo
使用此代码,我将删除第2列中
foo
的匹配项:

awk'BEGIN{FS=OFS=“,”};{if($2!~/foo/)打印$0}'

我得到了这个输出,我期望:

foo,bar
foo,bar
接下来,我在
if
语句中添加一个附加条件,以删除第2列中与
bar
匹配的所有值:

awk'BEGIN{FS=OFS=“,”};{如果($2!~/foo/| |$2!~/bar/)打印$0}'

我得到了这个输出,这是我没有预料到的:

foo,bar
bar,foo
foo,bar
bar,foo
我希望不会返回任何行,这是我的目标。发生了什么事

这两个条件是相互抵消的吗?我阅读了GNU awk的文档,其中说明:

“&&”和“| |”运算符因其工作方式而被称为短路运算符。如果在计算过程中可以部分确定结果,则对完整表达式的计算是“短路”的

从这个片段中,我不确定如何取得进展。还是语法不正确的问题?或者两者都有

更新:

在@wiktor stribiżew的评论和帮助下,这里有一个更好的问题描述:

1   2   3   4   5
foo bar foo bar FY 2008 Program Totals
foo bar foo bar FY 2009 Program Totals
foo bar foo bar Fiscal Year 2010 Program Totals
foo bar foo bar Fiscal Year 2011 Program Totals
foo bar foo bar Fiscal Year 2012 Program Totals
foo bar foo bar Fiscal Year 2013 Program Totals
foo bar foo bar Fiscal Year 2014 Program Totals
foo bar foo bar Fiscal Year 2015 Program Totals
foo bar foo bar Fiscal Year 2016 Program Totals
foo bar foo bar Fiscal Year 2017 Program Totals
我的失败代码是:

awk'BEGIN{FS=OFS=“\t”};{如果($5!~/Fiscal.*计划总计/| |$5!~/FY.*计划总计/)打印$0}'


下面接受的答案解决了这个问题。

您希望筛选出字段2与
foo
bar
匹配的行,因此您希望该字段不等于
foo
bar
。因此,您需要
&&
运算符:

awk -F',' '$2 !~ /foo/ && $2 !~ /bar/' file > newfile
#                      ^^
注意:如果将条件分组并否定结果,也可以使用
|

awk -F\, '!($2 ~ /foo/ || $2 ~ /bar/)' file > newfile
注意:您不需要设置OFS的
,因为您只打印
$0
(整行),而且这是默认操作,如果您按照上面所示编写条件,则无需指定。

您只需:

awk '$2 !~ /foo|bar/' file
考虑到您真正失败的代码:

awk 'BEGIN { FS=OFS="\t" } ; { if ($5 !~ /Fiscal.*Program Totals/ || $5 !~ /FY.*Program Totals/) print $0}'
假设您的字段真的是按代码所示的制表符分隔的,您可以这样写:

awk -F'\t' '$5 !~ /F(iscal|Y).*Program Totals/'

有用的解释,谢谢,但它并没有解决我的生产数据问题。它是用制表符分隔的,所以我必须设置
FS
OFS
。我试图过滤掉的输入如下,在一个指定的列中(
$5
,恰如其分):``2008财年计划总计FY 2009财年计划总计2010财年计划总计FY 2011财年计划总计`awk-F'\t'$5!~/财务。*项目总额/&&$5!~/FY.*程序总计/'文件不会删除它们。@tesolat然后使用
-F'\t'
,您仍然不需要设置OFS的
抱歉,我无意中按了返回键。已编辑-其中也应该有一个代码块,但它没有呈现。@tesolat。请不要设置OFS,在这种情况下它是没有意义的。当然,除非你想更改字段分隔符。很好的解决方案@ed morton,谢谢。我已经选择了Wiktor的答案,因为它解决了条件和逻辑运算符的使用问题,我需要更多地使用它们。不客气。没关系,这并不是你如何解决问题中描述的问题。你使用的正则表达式是解决问题的一种方法,但我应该更清楚的是,我需要扩展条件和运算符的使用,这些需要成为解决方案的一个组成部分。