Bash-如果主域位于文件A(或管道)中,则从文件B中删除域/子域

Bash-如果主域位于文件A(或管道)中,则从文件B中删除域/子域,bash,awk,grep,Bash,Awk,Grep,我希望能够使用域的管道输入或引用文件(文件B)从文件a中删除每个域及其子域 例如,我不能使用grep“bbc.co.uk”,因为这将包括cbbc.co.uk等条目 我尝试使用while read循环来迭代文件B,运行grep-E“^([^.\s]+\)*${escaped_domain}$”文件a,以识别域和子域,但这非常非常慢,需要进行大量的比较 有更好的方法吗?也许用awk 文件B(或管道输入) 约3万条线路 bbc.co.uk amazon.co.uk doubleclick.net 文

我希望能够使用域的管道输入或引用文件(文件B)从文件a中删除每个域及其子域

例如,我不能使用
grep“bbc.co.uk”
,因为这将包括
cbbc.co.uk
等条目

我尝试使用while read循环来迭代文件B,运行
grep-E“^([^.\s]+\)*${escaped_domain}$”文件a
,以识别域和子域,但这非常非常慢,需要进行大量的比较

有更好的方法吗?也许用awk

文件B(或管道输入)

约3万条线路

bbc.co.uk
amazon.co.uk
doubleclick.net
文件A

约150k+条线路

123123.test.bbc.co.uk
123434.rwr.amazon.co.uk
ads.bbc.co.uk
adsa.23432.doubleclick.net
amazon.co.uk
bbc.co.uk
cbbc.co.uk
damazon.co.uk
fsdfsfs.doubleclick.net
test.amazon.co.uk
test.bbc.co.uk
test.damazon.co.uk
所需输出:

cbbc.co.uk
damazon.co.uk
test.damazon.co.uk
当前方法(与grep/regexps不同的输入)

#转换输入:地址=/test.com/->^([^.\s]+\)*test\.com$
regexList=$(cat fileB|
sed's/\./\\./g'|
awk-F'/'{'print'^([^.\s]+\)*“$2”$”})
而read-r正则表达式;做
grep-E$regex filaA

完成您可以将第一个文件转换为一组正则表达式,以便删除:

sed 's/[][\\.^$*+?()]/\\&/g;s/.*/^([^.]+\\.)*&$/' fileB
输出是一个正则表达式序列,可以传递到
grep-vE

... | grep -vEf - fileA

grep-Ef一次可以在内存中保留多少内存是有限制的,但是30k表达式在现代硬件上可能是有限的。在最坏的情况下,将
fileA
一分为二,并运行两次该过程。

您可以将第一个文件转换为一组正则表达式,以便删除:

sed 's/[][\\.^$*+?()]/\\&/g;s/.*/^([^.]+\\.)*&$/' fileB
$ awk '
    NR==FNR {
        gsub(/[^^]/,"[&]")
        gsub(/\^/,"\\^")
        doms["(^|[.])"$0"$"]
        next
    }
    {
        for (dom in doms) {
            if ($0 ~ dom) {
                next
            }
        }
        print
    }
' fileB fileA
cbbc.co.uk
damazon.co.uk
test.damazon.co.uk
输出是一个正则表达式序列,可以传递到
grep-vE

... | grep -vEf - fileA
grep-Ef一次可以在内存中保留多少内存是有限制的,但是30k表达式在现代硬件上可能是有限的。在最坏的情况下,将
fileA
一分为二,并运行该进程两次

$ awk '
    NR==FNR {
        gsub(/[^^]/,"[&]")
        gsub(/\^/,"\\^")
        doms["(^|[.])"$0"$"]
        next
    }
    {
        for (dom in doms) {
            if ($0 ~ dom) {
                next
            }
        }
        print
    }
' fileB fileA
cbbc.co.uk
damazon.co.uk
test.damazon.co.uk
或使用管道:

$ cat fileB | awk '...' - fileA
如果fileB足够小,则不需要阵列,只需为所有域构建并测试1个regexp即可:

$ awk '
    NR==1 { doms = "(^|[.])(" $0; next }
    NR==FNR {
        gsub(/[^^]/,"[&]")
        gsub(/\^/,"\\^")
        doms = doms "|" $0
        next
    }
    FNR==1 { doms = doms ")$" }
    $0 !~ doms
' fileB fileA
cbbc.co.uk
damazon.co.uk
test.damazon.co.uk
每个脚本中的2
gsub()。请参阅,了解其工作原因和方式的详细信息

或使用管道:

$ cat fileB | awk '...' - fileA
如果fileB足够小,则不需要阵列,只需为所有域构建并测试1个regexp即可:

$ awk '
    NR==1 { doms = "(^|[.])(" $0; next }
    NR==FNR {
        gsub(/[^^]/,"[&]")
        gsub(/\^/,"\\^")
        doms = doms "|" $0
        next
    }
    FNR==1 { doms = doms ")$" }
    $0 !~ doms
' fileB fileA
cbbc.co.uk
damazon.co.uk
test.damazon.co.uk

每个脚本中的2
gsub()。请参阅以了解其工作原因和方式的详细信息。

例如,我不能使用grep“bbc.co.uk”,因为这将包括cbbc.co.uk等条目,您可以使用
grep-Eo“\bbbc.co.uk\b
我以前试过使用单词边界。不幸的是,这与
my bbc.co.uk
之类的内容相匹配,使得它有点过于敏感。@RavinderSingh13输出不应包括那些域,因为
doubleclick.net
位于
文件B
adsa.23432.doubleclick.net
doubleclick.net
的子域,因此不应输出。我们很容易混淆。将第一个输入文件命名为B,将第二个命名为A是不必要的混淆。不必记住问题中的第一个输入文件名为
fileB
,就很难弄清楚某人需要做什么以及如何帮助他们!当然,现在不要更改,否则会让事情变得更糟,但下次……例如,我不能使用grep“bbc.co.uk”,因为这将包括cbbc.co.uk等条目,您可以使用
grep-Eo“\bbbc.co.uk\b
我以前试过使用单词边界。不幸的是,这与
my bbc.co.uk
之类的内容相匹配,使得它有点过于敏感。@RavinderSingh13输出不应包括那些域,因为
doubleclick.net
位于
文件B
adsa.23432.doubleclick.net
doubleclick.net
的子域,因此不应输出。我们很容易混淆。将第一个输入文件命名为B,将第二个命名为A是不必要的混淆。不必记住问题中的第一个输入文件名为
fileB
,就很难弄清楚某人需要做什么以及如何帮助他们!当然,现在不要更改它,否则会让事情变得更糟,但下一次…@EdMorton,谢谢,以前从未见过,字符类中反斜杠的位置必须更改。我以为我加倍反斜杠是格外小心,但那根本没用。这可能还不是完全可移植的。看起来它对我来说是可移植的。我唯一想知道的是,你是否真的能逃脱这些魔咒。在我参与的另一个关于转义regexp元字符的问题中,我们最终将除了
^
之外的所有字符都放在括号表达式中,并且只转义了
^
(请参见),但我不记得在什么情况下仅仅转义它们是不够的。也许只是因为我们没有假设ERE,所以不得不担心意外启用ERE元字符?idk…@EdMorton,谢谢,以前从未见过,字符类中反斜杠的位置必须更改。我以为我加倍反斜杠是格外小心,但那根本没用。这可能还不是完全可移植的。看起来它对我来说是可移植的。我唯一想知道的是,你是否真的能逃脱这些魔咒。在我参与的另一个关于转义regexp元字符的问题中,我们最终将除了
^
之外的所有字符都放在括号表达式中,并且只转义了
^
(请参见),但我不记得在什么情况下仅仅转义它们是不够的。也许只是因为我们没有假设ERE,所以不得不担心意外启用ERE元字符?idk…谢谢-我正在尝试;看起来确实如此