grep/perl正则表达式,用于查找标题和匹配行

rjjhvcjd  于 2022-11-15  发布在  Perl
关注(0)|答案(3)|浏览(129)

假设我有一个文件,名为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,但不知道如何打印课程提供商名称与电子邮件和课程名称。
有什么想法?

kmbjn2e3

kmbjn2e31#

如果您在段落中处理(由空行分隔的文本块),那么在每个段落中匹配所需的模式是相当简单的--标题(后面是一行=)和一行java

perl -00 -wnE'say "$1\n$2" 
    if /(.+?) \n "=+.+? \n .+? \n ([^\n]+\sjava\s[^\n]+)/sx' file

(在Linux上测试;请继续阅读Windows版。2为了便于阅读,请将其分成几行。3请参阅下面对该模式的解释。)
在带有= s的行尾,我使用.+?代替输入中= s后面的特定字符,因为示例输入不一致;在不同的段落中,它同时具有-""-。根据需要进行调整。
由于这是在Windows上,您可能必须使用"作为单行程序的分隔符(我不知道您使用的是什么shell),因此您可能需要将模式中的文字"替换为\x22"的十六进制),或者其他您喜欢的序列。
希望适用于Windows(目前无法在Windows上测试)

perl -00 -wnE "say qq($1\n$2) 
    if /(.+?)\n \x22=+.+? \n .+? \n ([^\n]+\sjava\s[^\n]+) /sx
" file

开关-00使它按段落读。使用/x修饰符时,模式中的空格被忽略,因此我们可以用它们来分隔内容以提高可读性。使用/s修饰符时,.也匹配一个换行符。这对于中间的.+?匹配多行非常重要。直到java(被空格包围)。†
如果您不介意使用脚本而不是一行程序,那么我的建议是,例如

use warnings;
use strict;
use feature 'say';

local $/ = "\n\n";

while (<>) { 
    say "$1\n$2" 
        if /(.+?) \n "=+.+? \n .+? \n ([^\n]+ \sjava\s [^\n]+)/sx;
}

〈〉操作符逐行读取命令行中给定的文件,但“行”的概念在前面被设置为带有local $/ = "\n\n"的段落。如果这是一个较大程序的一部分,而您不想更改整个程序的$/变量,那么这个局部变量就在那里!
†或者,不要使用/s来匹配换行符,而是使用多行模式

perl -00 -wnE'say "$1\n$2" 
    if /(.+) \n "=+.+ \n (?:.+\n)* (.+\sjava\s.+)/x' file

或者,如果您需要Windows上的"...",例如

perl -00 -wnE "say qq($1\n$2) 
    if /(.+) \n \x22=+.+ \n (?:.+\n)* (.+\sjava\s.+)/x' file

(同样,我现在无法在Windows上进行测试。)
请注意,现在我们不必像上面的/s模式那样,通过添加?.+?)来使所有.+非贪婪--现在.+在一个换行符处停止,这正是这里所需要的。
或者,通过扩展模式动态使用/s修饰符

perl -00 -wnE "say "$1\n$2" 
    if /(.+) \n \x22=+.+ \n (?s).+?(?-s) (.+\sjava\s.+)/x
" file

这里(?s)“打开”/s修饰符,它将一直有效到封闭组的结尾(在本例中是模式的其余部分),但是(?-s)将其关闭。

mum43rcc

mum43rcc2#

我不会给予你一个完整的解决方案,但你可以从这个开始:

grep -iE "java|@" filename.txt

有人解释:

  • -i使其不区分大小写
  • -E使用扩展的正则表达式
  • |是这些扩展正则表达式的一个示例,它表示“OR”:显示包含“java”或“@”的行(后者是所有电子邮件地址)

结果,您将得到一个包含所有电子邮件地址和所有'java'课程的文件,还包含一个catch:如果一行中有一个电子邮件地址,后面跟着另一行,那么这个地址就没有'java'课程了。因此,现在可以使用Perl删除下一行中也是电子邮件地址的电子邮件地址。

xmjla07d

xmjla07d3#

查看输入数据,我们可以得出结论,该部分以包含电子邮件地址的行开始。
该部分的数据以序列号开头。
基于这些信息,我们可以构建一个散列值%sections,其中line包含email作为一个 key,所有以serial number开头的行都可以存储在该key下的一个 array 中。
一旦构建了散列,代码将遍历所有部分并查找包含搜索项的行,如果搜索项找到了具有匹配 * 行 * 的输出 * 部分 *。
注意:要处理真实的文件,请将<DATA>替换为<>,然后以./script.pl filename.dat运行

use strict;
use warnings;
use feature 'say';

my($lookfor, %sections, $key);

$lookfor = shift || die "Provide search term";

while( <DATA> ) {
    chomp;
    $key = $_ if /@/;
    push @{$sections{$key}}, $_ if /^\d\) /;
}

for my $section (keys %sections ) {
    for( @{$sections{$section}} ) {
        say "$section\n"
          . '-' x 30
          . "\n$_\n" if /\b$lookfor\b/i;
    }
}

exit 0;

__DATA__
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  
==========================-    
<br>

输出量

edX (anjan.fizz@gmail.com)
------------------------------
7) java

coursera (anjan.foo@gmail.com)
------------------------------
3) java concurrency

udemy (anjan.bar@gmail.com)
------------------------------
2) java programming language

相关问题