我在文件 1 中有正则表达式
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8802.*.*.*.*84231655.*
还有很多其他文件包含如下记录:
0081347504;03.05.2019 10:51;000010;000000001000126289;8601;Kontaktschreiben;;;;;00000000000901326394;
0081349117;03.05.2019 10:51;000020;000000002000044721;8906;Termin vereinbaren;;;07.05.2019;10:00;14:00;00000000000901332422;
0081349117;03.05.2019 10:51;000030;000000002000044722;8906;Termin vereinbaren;;;07.05.2019;10:00;14:00;00000000000901332423;
0081351563;03.05.2019 10:52;000010;000000001000116607;8906;Termin vereinbaren;;;06.05.2019;13:00;18:00;00000000000901332339;
我想要grep
文件 2 中文件 1 中的每条记录。
我已经尝试过grep -Ff file 1 ./*
但不起作用。
答案1
稍微整洁一点也没什么坏处。
首先,我认为你可能感到困惑regexes
和Globbing
;并且无论哪一行,您都不需要重复同一行两次或更多次(可能您试图表明您有很多行要解释为regexes
,但您懒得使每一行都唯一...但是,只是为了确定)。所以这:
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8912.*.*.*.*81415444.*
.*8802.*.*.*.*84231655.*
可以用这个代替:
.*8912.*.*.*.*81415444.*
.*8802.*.*.*.*84231655.*
好吧...现在怎么办?...好吧,grep
它会将每一行用作 a regex
(不globbing
on grep
),因此,该文件中的每一行都应该是 a regex
,... 因此,如果您尝试匹配:
在8912
在81415444
在
在哪里在代表:任何事物
这:
.*8912.*81415444.*
就足够了。
然后,在您的文件中使用它regex
:
.*8912.*81415444.*
.*8802.*84231655.*
但是,如果您想匹配:
点 在8912点 在 点 在 点 在 点 在81415444点 在
在哪里在代表:任何事物和点代表文字点,这regex
是错误的,因为在 中regexes
,一个点是一个meta-character
...你需要逃离每一个文字点带有backslash
> \
,所以,正则表达式应该是:
\..*8912\..*\..*\..*\..*81415444\..*
然后,在您的文件中使用它regex
:
\..*8912\..*\..*\..*\..*81415444\..*
\..*8802\..*\..*\..*\..*84231655\..*
或者,您可以使用egrep
与 相同的grep --extended-regexp
,来使用扩展正则表达式,并简化你的正则表达式限制重复,并以更紧凑的方式与上面完全相同,如下所示:
\..*8912(\..*){4}81415444\..*
\..*8802(\..*){4}84231655\..*
(您可以在没有扩展正则表达式的情况下执行类似的操作,但您需要使用更多反斜杠,如下所示\..*8912\(\..*\)\{4\}81415444\..*
:)
现在,假设您位于一个包含两个目录的目录中:一个是正则表达式(带有正则表达式文件的一个),另一个是样本文件(包含您想要与正则表达式匹配的文件的文件)...
然后,您可以使用此命令来实现您的目标:
grep --colour -f ./regex/YOUR_REGEX_FILENAME ./sample_files/*
你会得到一些输出,如下所示:
./sample_files/sample_file2:0088027504;03.05.2019 10:51;000010;000000008423165589;8601;Kontaktschreiben;;;;;00000000000901326394;
./sample_files/sample_file7:0089128117;03.05.2019 10:51;000030;000000002814154447;8906;Termin vereinbaren;;;07.05.2019;10:00;14:00;00000000000901332423;
你可能会说:为什么有两个单独的目录?好吧,这并不是真正必要的,但是,问题是,如果您的示例文件和正则表达式文件位于同一目录中,并且您使用如下命令:
grep -f file_1 ./*
这./*
是使用通配符,并将匹配当前目录中的任何文件,包括您的正则表达式文件...
在这种情况下,您可以做的是,例如,向您的正则表达式文件添加一些独特的扩展名,例如,,.regex
然后更改此文件的通配模式:./!(*.regex)
...此通配将排除以 ... 结尾的文件.regex
,然后,你的命令是:
grep -f file_1.regex ./!(*.regex)
最后,请注意:您不能在 shell 中使用带有空格的名称,而不转义它们:您可以使用反斜杠转义每个空格,或者可以用引号将全名括起来。
答案2
除了 matsib.dev 的出色回答之外:
您确定 -F 标志吗?它关闭正则表达式并让 grep 搜索固定字符串。因此.*
只会命中包含点后跟星号的行。
另一件需要检查的事情是文件的内容1
。如果它具有类似 dos 的行结尾(即行以 CRLF 而不是单个 LF 结尾),grep -f 1
则将搜索以 CR 或 ^M 结尾的字符串。检查这一点的最快方法:cat -A 1
。如果您在每行末尾看到 ^M,则说明您有问题。