在段落模式中匹配“模式文件”中的多个模式

在段落模式中匹配“模式文件”中的多个模式

我有一个输入文件,必须在段落中搜索不同的匹配项,并在匹配时将其移至包含整个段落的输出文件。

一件事是输出的顺序应该反映输入的顺序。所以我必须搜索一个段落全部来自模式匹配文件的模式(每行一个模式),并且如果模式匹配它应该停止对该段落的进一步匹配,并将匹配的段落移动到输出文件,并跳过处理到下一个段落。

输入文件:

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问题,这些问题超出了我的想象:

  1. 使用输入文件来匹配模式
  2. 在第一个匹配项上旋转段落并“停止/跳转到下一段”
  3. 将匹配的段落复制到输出文件。
  4. 删除输入中匹配的段落(可选,因为我可以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])改为使用。

相关内容