我想找出 2 个逗号分隔文本文件列表之间的区别
I want to find the difference between 2 lists of comma dilimited text files
我有 2 个逗号分隔的文本文件。
文件 1 包含单个逗号分隔行
Brad@blah.com, jo@me.com.au, Josh@yahoo.co.uk
文件 2 包含单个逗号分隔行
George@here.com, brad@blah.com, sister@me.com.au, jo@me.com.au, josh@yahoo.co.uk
我想显示文件 2 中但不在文件 1 中的电子邮件地址,这样生成的文件 3 将包含文本
George@here.com, sister@me.com.au
我一直在尝试使用 grep 寻找解决方案,但任何 windows 工具都可以。
假设您有多个电子邮件地址,这些地址由逗号分隔,周围可以有空格和制表符,
awk -F'[ \t]*,[ \t]*' 'NR == FNR { for(i = 1; i <= NF; ++i) seen[tolower($i)] } NR != FNR { for(i = 1; i <= NF; ++i) { if(!(tolower($i) in seen)) { print $i } } }' file1 file2
awk代码为
NR == FNR { # in the first file (overall line ==
# line in file)
for(i = 1; i <= NF; ++i) { # for all fields in the line:
seen[tolower($i)] # remember that you saw it.
}
}
NR != FNR { # in subsequent files (here the second)
for(i = 1; i <= NF; ++i) { # for all fields in the line:
if(!(tolower($i) in seen)) { # if you've not seen it before
print $i # print it.
}
}
}
编辑: 改编自@JID 评论的更简单版本是
awk -v RS='\n|[ \t]*,[ \t\n]*' 'NR == FNR { seen[tolower([=12=])] } !(tolower([=12=]) in seen)' file1 file2
JID 是正确的,使用记录分隔符可以使代码更简单——如果将文件直接拆分为电子邮件地址记录,for 循环就变得不必要了。我稍微更改了他的记录分隔符以避免在尾随逗号和换行符之间引入空记录,并允许逗号前有空格。
这种简化的方法适用于 mawk
和 gawk
,它们是当今最常见的 awk。然而,正则表达式记录分隔符不是 POSIX 的一部分,因此这可能会在某些旧的 Unice 上中断。在这种情况下,请参考第一种非简化方法。这应该适用于任何地方——正则表达式字段分隔符 are POSIX-conforming.
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "file3line="
FOR /f "delims=" %%a IN (q28085343_file1.txt) DO (
FOR /f "delims=" %%b IN (q28085343_file2.txt) DO (
FOR %%s IN (%%b) DO (
SET "found="
FOR %%t IN (%%a) DO IF /i "%%s"=="%%t" SET found=Y
IF NOT DEFINED found SET "file3line=%%s, !file3line!"
)
)
)
IF DEFINED file3line ECHO(%file3line:~0,-2%
GOTO :EOF
我使用了一个名为 q28085343_file1.txt
和 q28085343_file2.txt
的文件,其中包含您的数据用于我的测试。
我有 2 个逗号分隔的文本文件。
文件 1 包含单个逗号分隔行
Brad@blah.com, jo@me.com.au, Josh@yahoo.co.uk
文件 2 包含单个逗号分隔行
George@here.com, brad@blah.com, sister@me.com.au, jo@me.com.au, josh@yahoo.co.uk
我想显示文件 2 中但不在文件 1 中的电子邮件地址,这样生成的文件 3 将包含文本
George@here.com, sister@me.com.au
我一直在尝试使用 grep 寻找解决方案,但任何 windows 工具都可以。
假设您有多个电子邮件地址,这些地址由逗号分隔,周围可以有空格和制表符,
awk -F'[ \t]*,[ \t]*' 'NR == FNR { for(i = 1; i <= NF; ++i) seen[tolower($i)] } NR != FNR { for(i = 1; i <= NF; ++i) { if(!(tolower($i) in seen)) { print $i } } }' file1 file2
awk代码为
NR == FNR { # in the first file (overall line ==
# line in file)
for(i = 1; i <= NF; ++i) { # for all fields in the line:
seen[tolower($i)] # remember that you saw it.
}
}
NR != FNR { # in subsequent files (here the second)
for(i = 1; i <= NF; ++i) { # for all fields in the line:
if(!(tolower($i) in seen)) { # if you've not seen it before
print $i # print it.
}
}
}
编辑: 改编自@JID 评论的更简单版本是
awk -v RS='\n|[ \t]*,[ \t\n]*' 'NR == FNR { seen[tolower([=12=])] } !(tolower([=12=]) in seen)' file1 file2
JID 是正确的,使用记录分隔符可以使代码更简单——如果将文件直接拆分为电子邮件地址记录,for 循环就变得不必要了。我稍微更改了他的记录分隔符以避免在尾随逗号和换行符之间引入空记录,并允许逗号前有空格。
这种简化的方法适用于 mawk
和 gawk
,它们是当今最常见的 awk。然而,正则表达式记录分隔符不是 POSIX 的一部分,因此这可能会在某些旧的 Unice 上中断。在这种情况下,请参考第一种非简化方法。这应该适用于任何地方——正则表达式字段分隔符 are POSIX-conforming.
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "file3line="
FOR /f "delims=" %%a IN (q28085343_file1.txt) DO (
FOR /f "delims=" %%b IN (q28085343_file2.txt) DO (
FOR %%s IN (%%b) DO (
SET "found="
FOR %%t IN (%%a) DO IF /i "%%s"=="%%t" SET found=Y
IF NOT DEFINED found SET "file3line=%%s, !file3line!"
)
)
)
IF DEFINED file3line ECHO(%file3line:~0,-2%
GOTO :EOF
我使用了一个名为 q28085343_file1.txt
和 q28085343_file2.txt
的文件,其中包含您的数据用于我的测试。