我有两个列表,其中一个包含通配符(在本例中以*表示)。我想比较两个列表,并创建匹配的列表的输出,每个通配符*代表一个字符。
例如:
文件1
123456|Jane|Johnson|Pharmacist|janejohnson@gmail.com
09876579|Frank|Roberts|Butcher|frankie1@hotmail.com
092362936|Joe|Jordan|Joiner|joe@joesjoinery.com
928|Bob|Horton|Farmer|bhorton@farmernews.co.uk
文件2
1***6|Jane|Johnson|Pharmacist|janejohnson@gmail.com
09876579|Frank|Roberts|Butcher|f**1@hotmail.com
092362936|Joe|Jordan|J*****|joe@joesjoinery.com
928|Bob|Horton|Farmer|b*****n@f*********.co.uk
输出
092362936|Joe|Jordan|Joiner|joe@joesjoinery.com
928|Bob|Horton|Farmer|bhorton@farmernews.co.uk
说明
前两行不视为匹配,因为* s的数量不等于第一个文件中显示的字符数。后两个是,因此将它们添加到输出中。
我已经尝试了一些方法来尝试在AWK中使用Join进行此操作,但是我什至不知道有什么方法可以尝试实现此目的。任何帮助将不胜感激。
答案 0 :(得分:1)
$ cat tst.awk
NR==FNR {
file1[$0]
next
}
{
# Make every non-* char literal (see https://stackoverflow.com/a/29613573/1745001):
gsub(/[^^*]/,"[&]") # Convert every char X to [X] except ^ and *
gsub(/\^/,"\\^") # Convert every ^ to \^
# Convert every * to .:
gsub(/\*/,".")
# Add line start/end anchors
$0 = "^" $0 "$"
# See if the current file2 line matches any line from file1
# and if so print that line from file1:
for ( line in file1 ) {
if ( line ~ $0 ) {
print line
}
}
}
$ awk -f tst.awk file1 file2
092362936|Joe|Jordan|Joiner|joe@joesjoinery.com
928|Bob|Horton|Farmer|bhorton@farmernews.co.uk
答案 1 :(得分:0)
sed 's/\./\\./g; s/\*/./g' file2 | xargs -I{} grep {} file1
说明:
我会利用正则表达式匹配。为此,我们需要将每个星号*
变成一个点.
,该点代表正则表达式中的任何字符。作为启用正则表达式的副作用,我们需要转义所有特殊字符,尤其是.
,以便按字面意义使用它们。在正则表达式中,我们需要使用\.
来表示一个点(而不是任何字符)。
第一步是使用sed
执行这些替换,第二步是将所有结果行作为搜索模式传递到grep
,并在file1
中搜索该模式。允许执行此操作的粘合剂是xargs
,其中{}
是占位符,代表sed
命令结果中的一行。
注意:
这不是一种简单,安全的通用解决方案,您只需复制并粘贴即可:在包含星号的文件中,请注意grep正则表达式中认为特殊的所有字符。