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
,如果是,则打印它。