awk:从文件中读取模式,awk '$2 !~ /{换行符分隔文件}/ && $1 > 5000'

awk: read pattern from file, awk '$2 !~ /{newline delimited file}/ && $1 > 5000'

提问人:Special Monkey 提问时间:8/9/2023 最后编辑:Special Monkey 更新时间:8/9/2023 访问量:91

问:

我有一个管道输出的命令,如下所示:

   1365 8.67.53.0.9
   2657 1.2.3.4
   5956 127.9.9.0
  10463 127.0.0.1
  15670 6.5.4.3.2
  17984 -

自:

awk '$2 !~ /-|127.0.0.1|6.5.4.3.2/ && $1 > 5000'

其中应打印:

   5956 127.9.9.0

或所有不包含 、 或 和 的 where 大于 。$2-127.0.0.16.5.4.3.2$15000

我想将所有应该忽略的值保留在换行符分隔的文件中,例如:

-
127.0.0.1
6.5.4.3.2

而不是在正则表达式中,因为我的这些列表会越来越多。/-|127.0.0.1|6.5.4.3.2/

理想情况下,这可以在单个命令中,而不是函数或 awk 程序文件中。另外,如果可能的话,我希望匹配更精确(不那么贪婪?我认为当前的正则表达式也会匹配 127.0.0.11 或 6.5.4.3.22 之类的东西。

bash 列表 文件 awk

评论

3赞 Charles Duffy 8/9/2023
请注意,在正则表达式中,正则表达式不仅匹配自身;它与任何东西都匹配。所以匹配../1.2.3.4/1A2B3C4
2赞 Charles Duffy 8/9/2023
不过,说到你的问题,awk 支持地图数据类型,因此您可以轻松地向地图添加键,以便在读取忽略文件时跟踪忽略文件中的元素(将忽略文件作为第一个输入,将数据文件作为第二个输入,然后您可以根据您所在的文件决定要执行哪种处理)。在这个网站上寻找任何一个(很多很多)例子,人们曾经像以前一样行事,你会看到你需要的所有活动部件已经在使用中。awkuniq
2赞 Ed Morton 8/9/2023
您的正则表达式未锚定,因此也与 的中间部分匹配。您应该使用全行字符串匹配,而不是部分单词正则表达式匹配。有关此问题的更多详细信息,请参阅 how-do-i-find-the-text-that-matches-a-pattern/1.2.3.4/21.2.3.45
2赞 Mark Reed 8/9/2023
你的正则表达式模式中有一个额外的;中间的不应该是吗?/|

答:

4赞 anubhava 8/9/2023 #1

您可以将要跳过的值保留在名为以下命令的文件中:skip

cat skip

-
127.0.0.1
6.5.4.3.2

然后使用这两个文件运行:awk

awk 'NR == FNR {omit[$1]; next} $1 > 5000 && !($2 in omit)' skip file

  5956 127.9.9.0

这里:

  • 在处理第一个文件时,即 我们将所有值存储在一个数组中。skipomit
  • 然后,在处理主文件时,我们只需检查数组中是否存在。$1 > 5000$2omit

评论

1赞 Special Monkey 8/9/2023
谢谢!这似乎有效。是否可以从通过管道传递到 awk 的上一个命令的输出中读取初始的 $1 和 $2,如 cat file |awk {这里是魔法的东西}
1赞 markp-fuso 8/9/2023
@SpecialMonkey用于指定来自 stdin 的输入,例如: ;请注意,最后 2 个参数 ... =>处理的第一个文件是,而处理的第二个“文件”实际上是 stdin (-cat file | awk 'magic stuff here' skip -skip -skip-)
2赞 Paolo 8/9/2023 #2

给定文件:input

127.0.0.1
6.5.4.3.2

和文件:file

   1365 8.67.53.0.9
   2657 1.2.3.4
   5956 127.9.9.0
  10463 127.0.0.1
  15670 6.5.4.3.2
  17984 -
# read input file and perform parameter substitution
$ ips=$(< input); ips=${ips//$'\n'/|}; ips=${ips//./[.]};
# create variable for regex
$ regex="^(-|${ips})$"
# pass regex to awk as variable and run logic
$ awk -v regex="$regex" '$2 !~ regex && $1 >5000' file
   5956 127.9.9.0