【问题标题】:finding multiple lines patterns and stop after first occurence找到多条线模式并在第一次出现后停止
【发布时间】:2018-11-15 16:24:33
【问题描述】:

我在不同的位置有很多文件,包括路径模式中的 */synth/debug/*,所有文件都有 *.list 扩展名。文件看起来像:

MODULE XYZ
SIGNED_A 0
WIDTH 12
SIGNED_B 1
(...)

MODULE XXX
SIGNED_A 1
WIDTH 12
SIGNED_B 0
(...and so on...)

我需要在 MODULE XXX 之后的前 3 行中找到第一个带有 MODULE XXX(XYZ 等相同)和 SIGNED*1 模式的文件并停止搜索。 SIGNED 字总是出现在 MODULE 之后的 1-3 行。

我有类似的东西:

find . -name *.list -path "*/synth/debug/*" -type f -exec grep -FHI "MODULE XXX" -A 3 {} \; | grep "SIGNED 1" -A 3 | head -1

但是得到了:

find: ‘grep’ terminated by signal 13

在第一次(正确)出现之后,该命令仍在搜索和解析文件,浪费时间。

【问题讨论】:

  • 您的预期输出是什么样的?很确定这对我来说是一个sed 问题。

标签: linux bash awk grep find


【解决方案1】:

使用 awk

find . -name *.list -path "*/synth/debug/*" -type f -exec awk '/MODULE XXX/{xxx=1;next}xxx{xxx+=1}/SIGNED.*1/&&xxx<=4{print FILENAME; exit}xxx>4{nextfile;}ENDFILE{xxx=0}' {} +

输出是符合条件的第一个文件的名称

如果文件包含多个 MODULE XXX 块,则删除 xxx&gt;4{nextfile;}

在 1 个命令中处理每个模块:

find . -name *.list -path "*/synth/debug/*" -type f -exec awk '/MODULE/{current=$2; line=1; next}current in results{next;}{line+=1}/SIGNED.*1/&&line<=4{results[current]=FILENAME}END{for(module in results){print module, results[module]}}' {} +

输出:模块名+第一个文件匹配条件:

ABC file2.txt
XXX file1.txt
XYZ file1.txt

【讨论】:

  • 当该模块的模式已经出现一次时,是否可以停止在其他文件中搜索模块 XXX?现在我得到了: XXX file1.txt (...) XXX file2.txt
  • @J.Doe 您使用了哪个命令?这应该是不可能的,两个命令都阻止了这种行为(第一个命令使用 exit 停止搜索其他文件,第二个命令使用关联数组并且一个键不可能有两个不同的值 + 有 current in results{next;} 停止搜索已经找到的模块)
  • 我正在使用第二个。我认为问题在于,file1.txt 和 file2.txt 位于不同的目录中: XXX /path1/file1.txt XXX /path2/file2.txt
  • @J.Doe : 你用find ... -exec awk ... {} \; 代替find ... -exec awk ... {} + 吗?第一个对每个文件运行一个 awk 命令,第二个对所有文件运行一次 awk。
  • 我使用了 find ... -exec awk ... {} + 并得到了某个路径的一个结果(即使在路径中有更多匹配模式的文件的情况下,这是正确的) ,但是当模式存在于另一个位置的文件中时 - 我得到了 MODULE XXX XXX /path1/file1.txt XXX /path2/file2.txt 的第二个结果
猜你喜欢
  • 2017-12-22
  • 2022-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-18
相关资源
最近更新 更多