![如何循环遍历文件并使每一行成为 awk 语句中的新正则表达式?](https://linux22.com/image/82938/%E5%A6%82%E4%BD%95%E5%BE%AA%E7%8E%AF%E9%81%8D%E5%8E%86%E6%96%87%E4%BB%B6%E5%B9%B6%E4%BD%BF%E6%AF%8F%E4%B8%80%E8%A1%8C%E6%88%90%E4%B8%BA%20awk%20%E8%AF%AD%E5%8F%A5%E4%B8%AD%E7%9A%84%E6%96%B0%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%9F.png)
文件A.txt:
ATGCATGC
GGGGGGTT
TTTTT
AAAA
文件B.txt:
asdfasdf
blah2
ATGCATGC
blah3
blah4
delte-me-too
GGGGGGTT
blah5
blah5
....
我想比较 FileA.txt 中的每一行并检查它是否在 FileB.txt 中。如果是在FileB中,我想删除以下内容:
匹配线
上面一行
下面两行
并输出到一个新文件中。
注意:FileA 中有 500,000 行。我想以一种不对模式进行硬编码的方式来做到这一点。
我目前有一些东西可以删除这些行,但是我对循环 FileA 来为此 awk 表达式创建新模式感到困惑:
awk '/$VARIABLE_REGEX/{for(x=NR-2;x<=NR+2;x++)d[x];} {a[NR]=$0}
END{for(i=1;i<=NR;i++)
if(!(i in d))
print a[i]}' FileB.txt
答案1
注意:没有错误检查。另外,假设第二个文件中的输入完全遵循提到的模式。
awk 'NR== FNR {a[$0] = $0 ; next } {if (!($0 in a)) {b[count++] = $0; } else {count--; if (count > 0) delete b[count];getline;getline; }} END {for (i=0; i<count; i++) print b[i] }' 1 2
输入在 1 和 2 中
1
ATGCATGC
GGGGGGTT
TTTTT
AAAA
2
asdfasdf
blah2
ATGCATGC
blah3
blah4
delte-me-too
GGGGGGTT
blah5
blah5
foo
foo-delete
AAAA
bar-delete
bar-delete
bar-ok
输出
asdfasdf
foo
bar-ok
答案2
下一个代码不是最佳的(因为它必须读取文件B.txt两次)但希望能更快awk
comm --nocheck-order -23 FileB.txt <(grep -B1 -A2 -Ff FileA.txt FileB.txt)
与新GNU sed您可以尝试的命令e
(为了节省内存)sed+grep:
sed 'N;h;s/.*\n//;s/.*/grep -xF "&" FileA.txt/e;/./{N;N;d};x;P;D' FileB.txt
答案3
这适用于您的样本
awk '
NR==FNR {patt[$0]; next}
$0 in patt {getline; getline; getline; prev=$0; next}
{print prev; prev=$0}
END {print prev}
' fileA.txt fileB.txt
你必须将文件 A 的所有内容保存在内存中,但你只需要一次记住文件 B 中的一行