![如何通过输入文件从文本文件中删除列中具有特定值的行?](https://linux22.com/image/139513/%E5%A6%82%E4%BD%95%E9%80%9A%E8%BF%87%E8%BE%93%E5%85%A5%E6%96%87%E4%BB%B6%E4%BB%8E%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E4%B8%AD%E5%88%A0%E9%99%A4%E5%88%97%E4%B8%AD%E5%85%B7%E6%9C%89%E7%89%B9%E5%AE%9A%E5%80%BC%E7%9A%84%E8%A1%8C%EF%BC%9F.png)
我有一个管道分隔文件,如下所示。
数据.txt
ESP|041336|46566|NY|CA
ESP|041337|46566|NY|CA
ESP|041338|46566|NY|CA
ESP|041339|46566|NY|CA
ESP|041340|46566|NY|CA
ESP|041341|46566|NY|CA
我有另一个文件,其中第二列中的值需要删除。
输入.txt
041337
041338
041339
我正在尝试删除第二列中具有 input.txt 值的行。
预期输出
ESP|041336|46566|NY|CA
ESP|041340|46566|NY|CA
ESP|041341|46566|NY|CA
我尝试使用 grep 来实现此目的,如下所示。
grep -vfw input.txt data.txt > output.txt
这不会删除列,但会引发错误“没有这样的文件或目录”并返回空文件。
答案1
如果您想将比较限制为仅与第二个分隔字段,则可以使用 awk 而不是 grep:
$ awk -F'|' 'NR==FNR {a[$1]++; next} !($2 in a)' input.txt data.txt > output.txt
$ cat output.txt
ESP|041336|46566|NY|CA
ESP|041340|46566|NY|CA
ESP|041341|46566|NY|CA
答案2
该选项-f
需要一个文件名。按照您的编写方式,文件名是f
, in后面的文本-vfw
,换句话说,它是w
.
您必须在末尾放置一个带有参数的选项(除了tar
,它使用奇怪的选项解析)。
其中任何一个都应该有效。
grep -v -w -f input.txt data.txt > output.txt
grep -vwf input.txt data.txt > output.txt
grep -vwfinput.txt data.txt > output.txt
注意:当您提出问题时,您应该始终完整引用确切的错误消息,其中提到了名称w
。
grep: w
: 没有这样的文件或目录
答案3
sed -nE '
/\|/!{H;1h;d;}
G
/^[^|]+\|([^|]+)\|.*\n\1(\n|$)/!P
' input.txt data.txt
结果:
ESP|041336|46566|NY|CA
ESP|041340|46566|NY|CA
ESP|041341|46566|NY|CA
评论:
input.txt
由于其中没有管道,因此将管线存放在保留空间中。/\|/!
这些行在保留空间中由换行符分隔。对于数据行,我们将保留区域附加到模式空间,然后尝试查找第二个管道分隔字段。如果找不到,则打印模式空间中第一个换行符之前的部分
P
。如果数据行(来自)中的第二个 - 分隔字段与位于模式空间末尾并由换行符分隔的输入字符串之一匹配,则正则表达式与
/^[^|]+\|([^|]+)\|.*\n\1(\n|$)/
模式空间匹配。它末尾有一个 OR 条件,用于处理匹配模式是文件最后一行的情况。|
data.txt
input.txt
假设 GNU sed 版本启用了扩展正则表达式以减少线路噪音。