假设我有一个文件,名为courses.txt的内容如下。该文件有部分(课程提供商和我的电子邮件使用)后面跟着各种课程。例如:edX(anjan. gmail.com),然后是各种课程名称,每个名称前面都有序列号。
udemy (anjan.bar@gmail.com)
"=========================="-
1) foo bar
2) java programming language
3) redis stephen grider
4) javascript
5) react with typescript
6) kotlin
7) Etherium and Solidity : the Complete Developer's Guide
8) reactive programming with spring
coursera (anjan.foo@gmail.com)
"==========================-"
1) python
2) typescript
3) java concurrency
4) C#
edX (anjan.fizz@gmail.com)
"==========================-"
1) excel
2) scala
3) risk management
4) stock
5) oracle
6) mysql
7) java
==========================-
问:我想用grep搜索一个课程,比如“java”。我想找到一个匹配,它会显示匹配的特定行(例如:“java”)和相应的节名称(例如“edX(anjan.fizz@ gmail.com)”)。
如果我想搜索“java”什么“regex”将给予我以下匹配(我在Windows上使用grep/perl):
<br>
udemy (anjan.bar@gmail.com)
2) java programming language
coursera (anjan.foo@gmail.com)
3) java concurrency
edX (anjan.fizz@gmail.com)
7) java
我尝试了lookbehind/lookahead,但不知道如何打印课程提供商名称与电子邮件和课程名称。
有什么想法?
3条答案
按热度按时间kmbjn2e31#
如果您在段落中处理(由空行分隔的文本块),那么在每个段落中匹配所需的模式是相当简单的--标题(后面是一行
=
)和一行java
(在Linux上测试;请继续阅读Windows版。2为了便于阅读,请将其分成几行。3请参阅下面对该模式的解释。)
在带有
=
s的行尾,我使用.+?
代替输入中=
s后面的特定字符,因为示例输入不一致;在不同的段落中,它同时具有-"
和"-
。根据需要进行调整。由于这是在Windows上,您可能必须使用
"
作为单行程序的分隔符(我不知道您使用的是什么shell),因此您可能需要将模式中的文字"
替换为\x22
("
的十六进制),或者其他您喜欢的序列。希望适用于Windows(目前无法在Windows上测试)
开关-00使它按段落读。使用
/x
修饰符时,模式中的空格被忽略,因此我们可以用它们来分隔内容以提高可读性。使用/s
修饰符时,.
也匹配一个换行符。这对于中间的.+?
匹配多行非常重要。直到java
(被空格包围)。†如果您不介意使用脚本而不是一行程序,那么我的建议是,例如
〈〉操作符逐行读取命令行中给定的文件,但“行”的概念在前面被设置为带有
local $/ = "\n\n"
的段落。如果这是一个较大程序的一部分,而您不想更改整个程序的$/变量,那么这个局部变量就在那里!†或者,不要使用
/s
来匹配换行符,而是使用多行模式或者,如果您需要Windows上的
"..."
,例如(同样,我现在无法在Windows上进行测试。)
请注意,现在我们不必像上面的
/s
模式那样,通过添加?
(.+?
)来使所有.+
非贪婪--现在.+
在一个换行符处停止,这正是这里所需要的。或者,通过扩展模式动态使用
/s
修饰符这里
(?s)
“打开”/s
修饰符,它将一直有效到封闭组的结尾(在本例中是模式的其余部分),但是(?-s)
将其关闭。mum43rcc2#
我不会给予你一个完整的解决方案,但你可以从这个开始:
有人解释:
-i
使其不区分大小写-E
使用扩展的正则表达式|
是这些扩展正则表达式的一个示例,它表示“OR”:显示包含“java”或“@”的行(后者是所有电子邮件地址)结果,您将得到一个包含所有电子邮件地址和所有'java'课程的文件,还包含一个catch:如果一行中有一个电子邮件地址,后面跟着另一行,那么这个地址就没有'java'课程了。因此,现在可以使用Perl删除下一行中也是电子邮件地址的电子邮件地址。
xmjla07d3#
查看输入数据,我们可以得出结论,该部分以包含电子邮件地址的行开始。
该部分的数据以序列号开头。
基于这些信息,我们可以构建一个散列值
%sections
,其中line包含email作为一个 key,所有以serial number开头的行都可以存储在该key下的一个 array 中。一旦构建了散列,代码将遍历所有部分并查找包含搜索项的行,如果搜索项找到了具有匹配 * 行 * 的输出 * 部分 *。
注意:要处理真实的文件,请将
<DATA>
替换为<>
,然后以./script.pl filename.dat
运行输出量