![使用 AWK 或 SED 从其他文件中删除变量,从而删除文件中的行](https://linux22.com/image/184048/%E4%BD%BF%E7%94%A8%20AWK%20%E6%88%96%20SED%20%E4%BB%8E%E5%85%B6%E4%BB%96%E6%96%87%E4%BB%B6%E4%B8%AD%E5%88%A0%E9%99%A4%E5%8F%98%E9%87%8F%EF%BC%8C%E4%BB%8E%E8%80%8C%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E8%A1%8C.png)
我想删除data.txt
包含文件中第二列参数之一的每一行keys.txt
。
keys.txt
2 aa 2 bb 2 cc 2 dd
data.txt
1 aa It is great 1 aa I want to delete this line 1 kk Really ? 1 bb Yes, I think so. 1 bb Why ? 1 kk Because I don't like the current situation 1 ll I want to change 1 cc Indeed it's a need 1 cc Sorry 1 zz Ok !
- 所需输出
1 kk Really ? 1 kk Because I don't like the current situation 1 ll I want to change 1 zz Ok !
我尝试使用以下awk
程序:
awk '
NR == FNR {pattern[$0]; next}
{
for (var in pattern) {
if ($0 ~ var) {
getline
next
}
}
print >> GoodFile.txt
}
' keys.txt
答案1
你已经很接近了,只遗漏了一些小点:
- 您需要将
data.txt
其作为参数添加到您的awk
调用中,否则该文件将不会被处理。 - 您当前正在将整行注册
keys.txt
到删除数据库中,因此您应该将其限制为第二个字段($2
而不是$0
)。 - 您用于检查是否应排除
if ($0 ~ var)
一行。data.txt
在这里,您也应该只比较该行的第二个字段,并且应该使用精确匹配 (==
) 而不是正则表达式匹配,以防止键可能包含正则表达式特有的字符的情况。 - 您从 打印
awk
,但实际上不需要。您可以改为重定向输出。
因此,稍微修改一下:
awk 'NR==FNR{pattern[$2];next} !($2 in pattern)' keys.txt data.txt > GoodFile.txt
keys.txt
这将在数组中注册每行的第二列pattern
,但对该文件不执行任何其他操作。对于,它将达到对每条线评估条件data.txt
的点。!($2 in pattern)
如果条件评估为“true”(即该行的第二列是不是在数组的索引中pattern
),将打印当前行。
答案2
您的脚本中的第一个问题是:
NR == FNR {pattern[$0]; next}
您使用整行作为数组的键pattern
,但您只需要第二个字段。您不需要同时使用next
和getline
,您只需next
移至下一行即可。您还忘记传递第二个文件作为输入。最后,您需要引用文件名,因为它只是一个字符串,而不是变量。修复这两个错误会产生:
awk '
NR == FNR {pattern[$2]; next}
{
for (var in pattern) {
if ($0 ~ var) {
getline
next
}
}
print >> "GoodFile.txt"
}
' keys.txt data.txt
现在,你是当然你想要>>
那里吗?这意味着awk
不会覆盖文件中已有的任何内容(例如,先前运行的输出)。>>
如果您只想awk
不覆盖单次运行的输出,则不需要>
就足够了。仅>>
当您想保留以前运行的数据时才需要,但我怀疑您不需要。
另外,根据您的数据,您实际上不想检查整行。您只想跳过data.txt
第二个字段与 中的第二个字段相同的行keys.txt
。如果是这样,这会更有效,特别是对于较大的文件:
awk '
NR == FNR {pattern[$2]; next}
{
if ($2 in pattern) {
next
}
print > "GoodFile.txt"
}
' keys.txt data.txt
或者,等效但更简洁:
awk '
NR == FNR {pattern[$2]; next}
{
if (!($2 in pattern) {
print > "GoodFile.txt"
}
}
' keys.txt data.txt
答案3
GNU sed
扩展正则表达式模式打开-E
,自动打印模式空间关闭-n
$ sed -En '
/^\S+\s+(\S+)$/{
s//\1/;H;d
}
G
/^\S+\s+(\S+)\s.*\n\1(\n|$)/!P
' keys.txt data.txt
假设密钥文件有两个字段,数据文件有两个以上。
第一步,我们将keys.txt 文件的第二个字段存储在hold 中。然后,在读取 data.txt 文件时,我们将键附加到 data.txt 文件的当前记录,并比较数据的第二个字段是否可以在键中的任何位置看到。仅当未找到时,我们才会打印数据。