bash - 如何快速删除文件中包含 BASH 中另一个文件列表中项目的行?

标签 bash optimization sed

我有一个名为 words.txt 的文件,其中包含一个单词列表。我还有一个名为 file.txt 的文件,每行包含一个句子。我需要快速删除 file.txt 中包含来自 words.txt 的行之一的任何行,但前提是在 {}

例如文件.txt:

Once upon a time there was a cat.
{The cat} lived in the forest.
The {cat really liked to} eat mice.

例如words.txt:

cat
mice

示例输出:

Once upon a time there was a cat.

被删除是因为在这两行中发现了“cat”,并且单词也在 {} 之间。

下面的脚本成功地完成了这个任务:

while read -r line
do
    sed -i "/{.*$line.*}/d" file.txt
done < words.txt

这个脚本很慢。有时 words.txt 包含数千个项目,因此 while 循环需要几分钟。我尝试使用 sed -f 选项,它似乎允许读取文件,但我找不到任何解释如何使用它的手册。

如何提高脚本的速度?

最佳答案

awk 解决方案:

awk 'NR==FNR{a["{[^{}]*"$0"[^{}]*}"]++;next}{for(i in a)if($0~i)next;b[j++]=$0}END{printf "">FILENAME;for(i=0;i in b;++i)print b[i]>FILENAME}' words.txt file.txt

它直接转换 file.txt 以获得预期的输出。

Once upon a time there was a cat.

未压缩版本:

awk '
    NR == FNR {
        a["{[^{}]*" $0 "[^{}]*}"]++
        next
    }
    {
        for (i in a)
            if ($0 ~ i)
                next
        b[j++] = $0
    }
    END {
        printf "" > FILENAME
        for (i = 0; i in b; ++i)
            print b[i] > FILENAME
    }
' words.txt file.txt

如果预计文件会变得太大以至于 awk 可能无法处理它,我们只能将它重定向到 stdout。我们可能无法直接修改文件:

awk '
    NR == FNR {
        a["{[^{}]*" $0 "[^{}]*}"]++
        next
    }
    {
        for (i in a)
            if ($0 ~ i)
                next
    }
    1
' words.txt file.txt

关于bash - 如何快速删除文件中包含 BASH 中另一个文件列表中项目的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24081493/

相关文章:

c++ - 为什么链接器优化如此糟糕?

mysql - 为什么我的列在 Django Admin 中排序很慢,只有 1 个问题表

matlab - 如何在Matlab中高效实现序数参数的优化

bash - 将一个文件中的字符串替换为第二个文件的内容

Bash 查找过滤器和复制 - 空格问题

bash - Gnuplot - 标签截断图

linux - 在邮寄过程中通过 shell 脚本将 csv 转换为 Excel

Bash 在变量中存储命令 PID 并终止进程

linux - 使用 sed 替换 Solaris 中的字符串

linux - 使用 find 和 sed 将文件名插入文件