我有两个文件。第一个(电子邮件)应根据第二个(域)进行清理。第一个是 15 GB,第二个是 160 MB。
dom=`cat file2.txt | xargs | sed -e "s/ /|/g"` ; sed -r "/$dom/d" file1.txt >> final_file.txt
这个命令给了我bash: /bin/sed: Argument list too long
。
答案1
听起来你只是想要:
grep -Fvf file2.txt file1.txt > final_file.txt
即存储在不包含 的任何行的final_file.txt
行中。file1.txt
file2.txt
-x
如果您想要的行file1.txt
不在 中,请添加该选项file2.txt
。或者-w
要匹配字(其中在或bar.com
中不匹配,但仍会在例如中匹配)。foobar.com
bar.common
foo.bar.com.us
但如果我们要查找千兆字节的数据和兆字节的不同字符串,即使这也需要很长时间。
使用诸如 之类的 shell 或支持进程替换的更快ksh
方法是zsh
:bash
export LC_ALL=C
comm -23 <(sort file1.txt) <(sort file2.txt) > final_file.txt
现在,如果正如您在评论中澄清的那样,file2.txt
它是一个域列表,并且您的意思是过滤掉以任何这些域结尾的file1.txt
行,那么更有效的方法是使用哈希表:@
awk -F@ '
! domains_processed {excluded[$0]; next}
! ($NF in excluded)
' file2.txt domains_processed=1 file1.txt > final_file.txt
您的方法存在问题:
无用的使用
cat
(UUOC)。cat
是连接文件。对于单个文件来说没有什么意义。您可以使用xargs < file
或< file xargs
使xargs
stdin 直接成为文件,而不是来自cat
仅推送文件内容的进程的管道。xargs
echo
默认调用。虽然echo
将其参数与此处所需的空格字符连接起来,但它还执行其他操作,其列表取决于实现。还xargs
期望以非常特定的格式输入。在这里,我希望您希望将 的每一行file2.txt
作为单独的参数传递给echo
您需要 GNU 特定的xargs -rd '\n'
.还将根据需要xargs
运行echo
多次,以避免参数大小的限制。因此,xargs
对于 160MB 的输入,输出将有几行。要将文件的行与特定字符连接起来,命令是
paste
:paste -sd '|' file2.txt
在这里,您通过将这些单词与 结合起来构建正则表达式
sed -r
(-r
作为 GNU 扩展)|
,但您并没有转义在这些行中找到的正则表达式运算符。如果这些是域名,请注意这.
是匹配任何字符的正则表达式运算符。与其他角色相处时你会遇到更大的问题。如果sed "/$dom/r"
您没有完全控制file2.txt
.如果
file2.txt
是 160MB 大,那么也会$dom
(或多或少)。命令行的大小是有限的。在 Linux 上,单个参数的大小也受到限制(最多 128KiB),因此您无法sed
通过参数传递脚本。它必须通过-f
.