unix 将egrep和sed与模式列表一起使用,以返回单个目标文件中每个模式的第一个示例

falq053o  于 2022-12-23  发布在  Unix
关注(0)|答案(2)|浏览(122)

我在一个文本文件中有一个很长的模式列表,每行一个项目。我使用的是旧版本的Solaris Unix,所以我必须在命令行中使用egrep,因为我的脚本编写经验非常有限。我正在搜索的文件中有每个模式的许多示例。我只想返回每个模式 * 的第一个示例 * 中的行

$ cat patterns.txt
p1
p2
p3

$ cat target.txt
p1
p3
p1
p1
p3
p2
p3
p2
p1

获取整个匹配列表的命令是

egrep -f patterns.txt target.txt

我已经找到了许多示例来说明如何只返回列表中模式的第一行,或者返回第一行和最后一行,我需要的是返回patterns.txt中每个模式的第一行到target.txt中
我已经尝试过使用awk和sed修改示例(如下所示),但是我对这些命令及其用法不是很熟悉,所以我可能做错了。

awk 'BEGIN { while(getline<"patterns.txt") M[$1]=1 }; { if(M[$1]==1) { print; M[$1]=2 } }' target.txt

egrep -f patterns.txt target.txt | sed -n '1p;$p'

最后一个生成了target.txt文件中匹配的第一个模式和最后一个模式,我认为这是朝着正确的方向前进,但是我对sed的理解还不够好,无法正确获得参数。

s6fujrry

s6fujrry1#

仅仅基于OP提供的数据,看起来我们只能匹配整行。
一个awk创意:

awk '
FNR==NR   {ptn[$0];next}             # 1st file: store line in array ptn[]; skip to next input line
$0 in ptn {print; delete ptn[$0]}    # 2nd file: if line is an index for the array then print line and delete array entry (so it will not match next time we see it)
' patterns.txt target.txt

# or as a one-liner sans comments:

awk 'FNR==NR {ptn[$0];next} $0 in ptn {print; delete ptn[$0]}' patterns.txt target.txt

这将产生:

p1
p3
p2

当然,我们不能仅仅从这个输出中判断出我们匹配了 * 哪 * 行,所以为了调试的目的,我们将向混合中添加一个显式的print,以包括输入行号:

$ awk 'FNR==NR {ptn[$0];next} $0 in ptn {print FNR,$0; delete ptn[$0]}' patterns.txt target.txt
1 p1
2 p3
6 p2
    • 注意:**虽然这(看起来)回答了OP对(有限的)提供的输入的问题,但我猜OP的真实世界数据可能涉及更多(例如,模式可能作为一行的子集存在;我们不需要匹配整个单词;我们不需要担心区分大小写的匹配;等);如果OP的实际需求更复杂,我建议尝试修改此处收到的任何答案(针对此问题和数据),如果不成功,则提出新问题,确保提供更现实的样本数据集
ego6inou

ego6inou2#

这可能对您有用(GNU sed):

sed 's#.*#/&/{x;/&/{x;d};s/^/\\n&/;x;b}#' filePatterns | sed -f - fileTarget

从模式文件生成一个sed脚本,并使用目标文件将该脚本应用于sed的第二次调用。

相关问题