bash: /bin/sed: 参数列表太长

bash: /bin/sed: 参数列表太长

我有两个文件。第一个(电子邮件)应根据第二个(域)进行清理。第一个是 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.txtfile2.txt

-x如果您想要的行file1.txt不在 中,请添加该选项file2.txt。或者-w要匹配(其中在或bar.com中不匹配,但仍会在例如中匹配)。foobar.combar.commonfoo.bar.com.us

但如果我们要查找千兆字节的数据和兆字节的不同字符串,即使这也需要很长时间。

使用诸如 之类的 shell 或支持进程替换的更快ksh方法是zshbash

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使xargsstdin 直接成为文件,而不是来自cat仅推送文件内容的进程的管道。

  • xargsecho默认调用。虽然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.

相关内容