Awk grep提前停止,每个模式一个匹配

Awk grep提前停止,每个模式一个匹配,awk,grep,Awk,Grep,假设我有一个模式驻留的文件,例如patterns.txt。我知道所有模式在另一个文件patterns\u copy.txt中只会匹配一次,在这种情况下,为了简化问题,只需复制patterns.txt 如果我跑 grep -m 1 --file=patterns.txt patterns_copy.txt > output.txt 我只有一行。我猜这是因为当两个文件的第一行匹配时,m标志停止了整个匹配过程 我想要实现的是让patterns.txt中的每个模式只匹配一次,然后让grep移动到

假设我有一个模式驻留的文件,例如patterns.txt。我知道所有模式在另一个文件patterns\u copy.txt中只会匹配一次,在这种情况下,为了简化问题,只需复制patterns.txt

如果我跑

grep -m 1 --file=patterns.txt patterns_copy.txt > output.txt
我只有一行。我猜这是因为当两个文件的第一行匹配时,m标志停止了整个匹配过程

我想要实现的是让patterns.txt中的每个模式只匹配一次,然后让grep移动到下一个模式

我如何做到这一点


谢谢。

您可以像这样循环您的模式(假设您使用的是Bash):

读取-r行时
;做
grep-m 1“$line”模式\u copy.txt
完成output.txt
或者,在一行中:

while read -r line; do grep -m 1 "$line" patterns_copy.txt; done < patterns.txt > output.txt
读取-r行时
;dogrep-m1“$line”模式_copy.txt;完成output.txt
对于并行处理,可以将进程作为后台作业启动:

读取-r行时
;做
grep-m 1“$line”模式\u copy.txt&
read-r line&&grep-m 1“$line”模式\u copy.txt&
#根据需要重复上一行
等待#等待此循环的greps完成
完成output.txt

对于每个循环,它都会等待最慢的grep完成,但这并不是很优雅,但应该比每个循环只有一个grep要快。

您可以像这样循环模式(假设您使用的是Bash):

读取-r行时
;做
grep-m 1“$line”模式\u copy.txt
完成output.txt
或者,在一行中:

while read -r line; do grep -m 1 "$line" patterns_copy.txt; done < patterns.txt > output.txt
读取-r行时
;dogrep-m1“$line”模式_copy.txt;完成output.txt
对于并行处理,可以将进程作为后台作业启动:

读取-r行时
;做
grep-m 1“$line”模式\u copy.txt&
read-r line&&grep-m 1“$line”模式\u copy.txt&
#根据需要重复上一行
等待#等待此循环的greps完成
完成output.txt

对于每个循环,它都会等待最慢的grep完成,但这并不是很优雅,但应该比每个循环只有一个grep要快。

更新的答案

我现在有机会将我所想的
awk
整合到
GNU并行
概念中

我使用
/usr/share/dict/words
作为我的
模式
文件,其中有235000行。在另一个答案中使用BenjaminW的代码需要141分钟,而这个代码只需要11分钟

这里的区别是没有临时文件,
awk
一旦找到了它要查找的所有8个东西,它就可以停止了

#!/bin/bash

# Create a bash function that GNU Parallel can call to search for 8 things at once
doit() {
   # echo Job: $9
   # In following awk script, read "p1s" as a flag meaning "p1 has been seen"
   awk -v p1="$1" -v p2="$2" -v p3="$3" -v p4="$4" -v p5="$5" -v p6="$6" -v p7="$7" -v p8="$8" '
      $0 ~ p1 && !p1s {print; p1s++;}
      $0 ~ p2 && !p2s {print; p2s++;}
      $0 ~ p3 && !p3s {print; p3s++;}
      $0 ~ p4 && !p4s {print; p4s++;}
      $0 ~ p5 && !p5s {print; p5s++;}
      $0 ~ p6 && !p6s {print; p6s++;}
      $0 ~ p7 && !p7s {print; p7s++;}
      $0 ~ p8 && !p8s {print; p8s++;}
      {if(p1s+p2s+p3s+p4s+p5s+p6s+p7s+p8s==8)exit}
   ' patterns.txt

}
export -f doit

# Next line effectively uses 8 cores at a time to each search for 8 items
parallel -N8 doit {1} {2} {3} {4} {5} {6} {7} {8} {#} < patterns.txt

更新的答案

我现在有机会将我所想的
awk
整合到
GNU并行
概念中

我使用
/usr/share/dict/words
作为我的
模式
文件,其中有235000行。在另一个答案中使用BenjaminW的代码需要141分钟,而这个代码只需要11分钟

这里的区别是没有临时文件,
awk
一旦找到了它要查找的所有8个东西,它就可以停止了

#!/bin/bash

# Create a bash function that GNU Parallel can call to search for 8 things at once
doit() {
   # echo Job: $9
   # In following awk script, read "p1s" as a flag meaning "p1 has been seen"
   awk -v p1="$1" -v p2="$2" -v p3="$3" -v p4="$4" -v p5="$5" -v p6="$6" -v p7="$7" -v p8="$8" '
      $0 ~ p1 && !p1s {print; p1s++;}
      $0 ~ p2 && !p2s {print; p2s++;}
      $0 ~ p3 && !p3s {print; p3s++;}
      $0 ~ p4 && !p4s {print; p4s++;}
      $0 ~ p5 && !p5s {print; p5s++;}
      $0 ~ p6 && !p6s {print; p6s++;}
      $0 ~ p7 && !p7s {print; p7s++;}
      $0 ~ p8 && !p8s {print; p8s++;}
      {if(p1s+p2s+p3s+p4s+p5s+p6s+p7s+p8s==8)exit}
   ' patterns.txt

}
export -f doit

# Next line effectively uses 8 cores at a time to each search for 8 items
parallel -N8 doit {1} {2} {3} {4} {5} {6} {7} {8} {#} < patterns.txt

使用
awk
,这是简单的答案@MarkSetchell,你能详细解释一下吗?实际上我对awk并不熟悉。谢谢。已经很晚了——也许@EdMorton会帮你做,或者我明天再做。尝试编辑标签并添加
awk
。使用
awk
,这是简单的答案@MarkSetchell,你能详细解释一下吗?实际上我对awk并不熟悉。谢谢。已经很晚了——也许@EdMorton会帮你做,或者我明天再做。尝试编辑您的标签并添加
awk
。这很酷!现在,如果我要搜索的文件很大(patterns_copy.txt文件,在Gb范围内),有没有快速的方法?我尝试了GNU并行,但结果不正确。谢谢您可以一次读几行,然后启动
grep
作为后台进程,使用
grep&。GNU parallel可能是更干净的解决方案,但我不熟悉它。太酷了!现在,如果我要搜索的文件很大(patterns_copy.txt文件,在Gb范围内),有没有快速的方法?我尝试了GNU并行,但结果不正确。谢谢您可以一次读几行,然后启动
grep
作为后台进程,使用
grep&。GNU并行可能是更干净的解决方案,但我不熟悉它。谢谢马克!我还没有尝试过你给出的解决方案,但是doit函数似乎可以满足我的需要。谢谢Mark!我还没有尝试过你给出的解决方案,但是doit函数似乎满足了我的要求。