1

全局域在“*@”选项中,当电子邮件与这些全局域之一匹配时,我需要将它们从列表中排除。

例子:

WF,*@stackoverflow.com
WF,*@superuser.com
WF,*@stackexchange.com
WF,test@superuser.com
WF,test@stackapps.com
WF,test@stackexchange.com

输出:

WF,*@stackoverflow.com
WF,*@superuser.com
WF,*@stackexchange.com
WF,test@stackapps.com
4

6 回答 6

3

你在同一个文件中有两种类型的数据,所以最简单的处理方法是先划分它:

<infile tee >(grep '\*@' > global) >(grep -v '\*@' > addr) > /dev/null

然后用于global从以下位置删除信息addr

grep -vf <(cut -d@ -f2 global) addr

把它放在一起:

<infile tee >(grep '\*@' > global) >(grep -v '\*@' > addr) > /dev/null
cat global <(grep -vf <(cut -d@ -f2 global) addr) > outfile

内容outfile

WF,*@stackoverflow.com
WF,*@superuser.com
WF,*@stackexchange.com
WF,test@stackapps.com

清理临时文件rm global addr

于 2012-10-29T10:59:57.107 回答
2

你可以这样做:

grep -o "\*@.*" file.txt | sed -e 's/^/[^*]/' > global.txt
grep -vf global.txt file.txt

这将首先提取全球电子邮件,并在它们前面加上[^*],将结果保存到global.txt. 然后将该文件用作 grep 的输入,其中每一行都被视为表单中的正则表达式[^*]*@global.domain.com。该-v选项告诉 grep 只打印与该模式不匹配的行。

使用 sed 进行就地编辑的另一个类似选项是:

grep -o "\*@.*" file.txt | sed -e 's/^.*$/\/[^*]&\/d/' > global.sed
sed -i -f global.sed file.txt
于 2012-10-29T10:40:34.920 回答
2
$ awk -F, 'NR==FNR && /\*@/{a[substr($2,3)]=1;print;next}NR!=FNR && $2 !~ /^\*/{x=$2;sub(/.*@/,"",x); if (!(x in a))print;}' OFS=, file file
WF,*@stackoverflow.com
WF,*@superuser.com
WF,*@stackexchange.com
WF,test@stackapps.com
于 2012-10-29T10:50:03.113 回答
2

这是使用GNU awk. 像这样运行:

awk -f script.awk file.txt{,}

内容script.awk

BEGIN {
    FS=","
}

FNR==NR {
    if (substr($NF,1,1) == "*") {
        array[substr($NF,2)]++
    }
    next
}

substr($NF,1,1) == "*" || !(substr($NF,index($NF,"@")) in array)

结果:

WF,*@stackoverflow.com
WF,*@superuser.com
WF,*@stackexchange.com
WF,test@stackapps.com

或者,这是单线:

awk -F, 'FNR==NR { if (substr($NF,1,1) == "*") array[substr($NF,2)]++; next } substr($NF,1,1) == "*" || !(substr($NF,index($NF,"@")) in array)' file.txt{,}
于 2012-10-29T11:18:09.197 回答
1

这可能对您有用(GNU sed):

sed '/.*\*\(@.*\)/!d;s||/[^*]\1/d|' file | sed -f - file
于 2012-10-29T13:27:51.890 回答
0

通过一次文件并允许将全局域与地址混合:

$ cat file
WF,*@stackoverflow.com
WF,test@superuser.com
WF,*@superuser.com
WF,test@stackapps.com
WF,test@stackexchange.com
WF,*@stackexchange.com
WF,foo@stackapps.com
$
$ awk -F'[,@]' '
   $2=="*" { glbl[$3]; print; next }
   { addrs[$3] = addrs[$3] $0 ORS }
   END {
      for (dom in addrs)
         if (!(dom in glbl))
            printf "%s",addrs[dom]
   }
' file
WF,*@stackoverflow.com
WF,*@superuser.com
WF,*@stackexchange.com
WF,test@stackapps.com
WF,foo@stackapps.com

或者如果您不介意 2-pass 方法:

$ awk -F'[,@]' '(NR==FNR && $2=="*" && !glbl[$3]++) || (NR!=FNR && !($3 in glbl))' file file
WF,*@stackoverflow.com
WF,*@superuser.com
WF,*@stackexchange.com
WF,test@stackapps.com
WF,foo@stackapps.com

我知道第二个有点神秘,但它很容易转换为不使用默认操作和 awk 习语中的一个很好的练习:-)。

于 2012-10-29T13:19:34.067 回答