如何在此特定文本上使用正则表达式捕获多个单词?

Rom*_*rio 3 regex perl

我正在尝试从以下示例文本中提取薪水最高的职位:

Data Scientist

#1 in Best Paying Jobs

5,100  Projected Jobs $250,000 Median Salary 0.5% Unemployment Rate

Programmer

#2 in Best Paying Jobs

4,000 Projected Jobs $240,000 Median Salary 1.0% Unemployment Rate

SAP Module Consultant

#3 in Best Paying Jobs

3,000 Projected Jobs $220,000 Median Salary 0.2% Unemployment Rate
Run Code Online (Sandbox Code Playgroud)

通过使用以下正则表达式和Perl代码。

use File::Glob;
local $/ = undef;
my $file = @ARGV[0];

open INPUT, "<", $file
    or die "Couldn't open file $!\n";

my $content = <INPUT>;

my $regex = "^\w+(\w+)*$\n\n#(\d+)";

my @arr_found = ($content =~ m/^\w+(\w+)*$\n\n#(\d+)/g);

close (INPUT);
Run Code Online (Sandbox Code Playgroud)

Q1:正则表达式仅查找一个单词的标题*。如何使其找到多个单词标题,以及如何将找到的标题转发(即如何正确捕获)到Perl数组中?

Q2:我将正则表达式定义为Perl变量,并尝试将该变量用于正则表达式操作,例如:

my @arr_found = ($content =~ m/"$regex"/g);
Run Code Online (Sandbox Code Playgroud)

但它给了错误。怎么做?

*当我^\w+(\w+)*$\n\n#(\d+)在Sublime Text 2上应用正则表达式时,它仅找到一个单词的标题。

zdi*_*dim 5

为什么不逐行处理,简单又容易

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

my $file = shift || die "Usage: $0 file\n";

open my $fh, '<', $file  or die "Can't open $file: $!";

my (@jobs, $prev_line);

while (my $line = <$fh>) { 
    chomp $line;
    next if not $line =~ /\S/;

    if ($line =~ /^\s*#[0-9]/) {
        push @jobs, $prev_line;
    }   

    $prev_line = $line;
}

say for @jobs;
Run Code Online (Sandbox Code Playgroud)

这取决于该#N行是作业标题之后的第一个非空行的要求。

它打印

数据科学家
程序员
SAP模块顾问

问题并没有说明是否也需要排名,但是正则表达式中暗示可能会排名。然后,假设文件中的顺序是“正确的”,则可以遍历数组索引并使用其索引(等级)打印元素(标题)。

或者可以肯定的是,将它们捕获在正则表达式中/^\s*#([0-9]+)/。然后,您可以直接打印标题及其排名,或者将它们存储在具有键值对的哈希中rank => title


至于正则表达式,需要一些更正。要在匹配之前编写一个正则表达式,这是一个好主意,您需要qr运算符。要使用多行字符串,您需要使用/m修饰符。(请参阅perlretut。)regex本身需要修复。例如

my $regex  = qr/^(.+)?(?:\n\s*)+\n\s*#\s*[0-9]/m;
my @titles = $content =~ /$regex/g
Run Code Online (Sandbox Code Playgroud)

捕获一行,然后至少一行空行,然后再捕获#N另一行。

如果还需要对标题进行排名,则也要对其进行捕获,并将其存储在哈希中

my $regex = qr/^(.+)?(?:\n\s*)+\n\s*#\s*([0-9]+)/m;
my %jobs  = reverse  $content =~ /$regex/g;
Run Code Online (Sandbox Code Playgroud)

或者最好不要通过reverse-ing匹配列表来推送它,而是遍历配对

my %jobs;
while ($content =~ /$regex/g) {
    $jobs{$2} = $1;
}
Run Code Online (Sandbox Code Playgroud)

因为这样我们可以在每次迭代中检查“捕获”,进行其他处理,等等。然后您可以对要排序的键进行排序

say "#$_ $jobs{$_}" for sort { $a <=> $b } keys %jobs;
Run Code Online (Sandbox Code Playgroud)

通常只是根据需要按职位等级选择工作。

我认为可以说这里的正则表达式比第一个程序复杂得多。