在文件中找到搜索字符串后需要命令 grep 未知行数

在文件中找到搜索字符串后需要命令 grep 未知行数

basefile.txt我有一个以大量行命名的文件。文件中的记录根据其集合进行逻辑分组。

例如:

"GRP_START","LINE1"........
"A"
"B--BOOM"
"C"
"GRP_START","LINE1"........
"A"
"B--DOOM"
"C"
"D"
"E"
"F"
"G"
"GRP_START","LINE1"........
"E"
"F"
"G"
"C--MOOM"
"GRP_START","LINE1"........

我想要做的是,我将这些搜索字符串放在一个名为的单独文件中,keywords.txt其中包含以下数据:

BOOM
DOOM
MOOM

我需要一个命令,它将从文件中一一读取文本keywords.txt并在 中搜索该文本basefile.txt并将某些记录写入finalfile.txt

这些特定记录是: 我需要搜索文本所在的集合。

例如:在上面的文件中。

该命令应该搜索 BOOM 并返回以下行

"GRP_START","LINE1"........
"A"
"B--BOOM"
"C"

该命令应搜索 DOOM 并返回以下行

"GRP_START","LINE1"........
"A"
"B--DOOM"
"C"
"D"
"E"
"F"
"G"

因此,GRP_START 是一组的开始,直到下一个 GRP_START 我希望将记录写入finalfile.txt.

答案1

以下awk脚本将读取数据文件并将每条记录临时存储在lines变量中。如果word在记录中找到变量中的关键字,则将该do_output变量设置为 1 (true)。当找到关键字并且我们到达下一条记录或文件末尾时,就会输出关键字记录。

#!/usr/bin/awk -f

/^"GRP_START"/ {
    if (do_output) {
        exit;
    }
    lines = $0;
    next;
}

$0 ~ word {
    do_output = 1;
}

{
    lines = sprintf("%s\n%s", lines, $0);
}

END {
    if (do_output) {
        print lines;
    }
}

测试它:

$ awk -v word="MOOM" -f script.awk basefile.txt
"GRP_START","LINE1"........
"E"
"F"
"G"
"C--MOOM"

然后只需循环所需的关键字即可:

#!/bin/sh

while read -r word; do
  awk -v word="$word" -f script.awk basefile.txt
done <keywords.txt >finalfile.txt

未来改进建议:先将关键字读入数组,然后basefile.txt仅解析一次数据文件。

答案2

尝试:

awk 'FNR==NR{re=re (re?"|":"")$0;next} /^"GRP_START"/{if (rec~re)print rec; rec=$0;next} {rec=rec"\n"$0} END{if (rec~re)print rec}' keywords.txt basefile.txt 

例子:

$ awk 'FNR==NR{re=re (re?"|":"")$0;next} /^"GRP_START"/{if (rec~re)print rec; rec=$0;next} {rec=rec"\n"$0} END{if (rec~re)print rec}' keywords.txt basefile.txt 
"GRP_START","LINE1"........
"A"
"B--BOOM"
"C"
"GRP_START","LINE1"........
"A"
"B--DOOM"
"C"
"D"
"E"
"F"
"G"
"GRP_START","LINE1"........
"E"
"F"
"G"
"C--MOOM"

怎么运行的

  • FNR==NR{re=re (re?"|":"")$0;next}

    在读取第一个文件 时keywords.txt,我们构造一个正则表达式来匹配任何单词。例如,对于示例数据,这将创建re值为 的变量BOOM|DOOM|MOOM

  • /^"GRP_START"/{if (rec~re)print rec; rec=$0;next}

    每次到达新记录的开头时,我们都会检查存储在中的最后一条记录是否与rec存储在中的正则表达式匹配re。如果是,我们就打印它。接下来,rec重置到当前行,我们跳过其余命令并跳转到该next行。

  • rec=rec"\n"$0

    对于所有其他行,我们将它们附加到rec.

  • END{if (rec~re)print rec}

    读完文件后,我们检查最终记录是否与正则表达式匹配re,如果是,则打印它。

相关内容