我有一个输入文件,必须在段落中搜索不同的匹配项,并在匹配时将其移至包含整个段落的输出文件。
一件事是输出的顺序应该反映输入的顺序。所以我必须搜索一个段落全部来自模式匹配文件的模式(每行一个模式),并且如果一模式匹配它应该停止对该段落的进一步匹配,并将匹配的段落移动到输出文件,并跳过处理到下一个段落。
输入文件:
DFJKHDKQW
YYYYYYYYYYYY
SDFLKJHSDKLFH
DSFLKHSDLKFH
DFIHERFW
ADFKJH
OIGHRFGH
XXXXXXXXXXXX
SDKFLJH
DFLKHSDFKLH
SDSDJKLFHSDK
OIHGSDFG
AAAAAAAA
LFKHFGJKDGH
KLJHLUG
DFSDKLF
YYYYYYYYYYYY
模式匹配文件:
AAAAAAAA
YYYYYYYYYYYY
XXXXXXXXXXXX
预期输出:
DFJKHDKQW
YYYYYYYYYYYY
SDFLKJHSDKLFH
DSFLKHSDLKFH
DFIHERFW
ADFKJH
OIGHRFGH
XXXXXXXXXXXX
SDKFLJH
OIHGSDFG
AAAAAAAA
LFKHFGJKDGH
KLJHLUG
DFSDKLF
YYYYYYYYYYYY
我现在面临着一系列awk
问题,这些问题超出了我的想象:
- 使用输入文件来匹配模式
- 在第一个匹配项上旋转段落并“停止/跳转到下一段”
- 将匹配的段落复制到输出文件。
- 删除输入中匹配的段落(可选,因为我可以
diff
稍后通过两个文件之间的 a 来执行此操作)。
答案1
假设您想要进行全行字符串匹配,这就是您所需要的:
$ cat tst.awk
BEGIN {
ORS = "\n\n"
FS = "\n"
}
NR==FNR {
tgts[$0]
next
}
{
out = "unmatched"
for (i=1; i<=NF; i++) {
if ($i in tgts) {
out = "matched"
break
}
}
print > out
}
$ awk -f tst.awk targets RS= file
$ ls *matched
matched unmatched
$ head -100 *matched
==> matched <==
DFJKHDKQW
YYYYYYYYYYYY
SDFLKJHSDKLFH
DSFLKHSDLKFH
DFIHERFW
ADFKJH
OIGHRFGH
XXXXXXXXXXXX
SDKFLJH
OIHGSDFG
AAAAAAAA
LFKHFGJKDGH
KLJHLUG
DFSDKLF
YYYYYYYYYYYY
==> unmatched <==
DFLKHSDFKLH
SDSDJKLFHSDK
如果您需要执行正则表达式而不是字符串匹配和/或部分而不是完全匹配或其他内容,那么您需要不同的解决方案(并请更新您的问题以更好地说明您的要求)。
答案2
匹配模式match
将每个作为单个单独的模式输入infile
输入,尝试:
awk -F'\n' '!input && !matches[$0]{ next; };
{ for(i=1; i<=NF; i++) {
if($i in matches) { print sep $0; sep=ORS; break; };
};
}' match input=1 RS= infile
或匹配模式match
输入作为针对的模式块infile
输入(添加一个与中相同的块match
输入到infile
来验证),尝试:
awk -v RS= '!input && !matches[$0]{ next; }; ($0 in matches)' match input=1 infile
答案3
由于您已经了解“段落”模式,因此以下方法应该有效。它将首先解析“模式”文件,然后解析实际输入。输出像往常一样打印到控制台,但当然可以重定向到文件:
awk -v ORS="\n\n" 'NR==FNR{pat[++npat]=$0;next}
{for (i=1;i<=npat;i++) {if (index($0,pat[i])) {print;next}}}' patterns.txt RS="" input.txt
这首先将输出记录分隔符设置为两个换行符,确保打印的段落与输入中一样由空行分隔。
当处理第一个文件时(其中
FNR
,每个文件行计数器等于NR
全局行计数器),我们只需将所有模式存储在一个数组变量中pat
。对于第二个文件,记录分隔符设置为空,这指示
awk
以“段落模式”运行。然后,我们迭代所有模式,并明确查看是否通过index()
函数在输入记录中找到它们。
笔记
该解决方案将执行“部分字符串匹配”,这意味着如果在其中一行中的任何地方遇到任何一种“模式”,则该段落将被视为匹配。
使用该
index()
函数是因为这将确保文字即使在“搜索模式”包含正则表达式特有的字符的情况下,字符串也会匹配。如果您想实际使用正则表达式匹配,请if ($0 ~ pat[i])
改为使用。