Perl正则表达式读取方括号:

4

我想读取方括号内的位,并且也想要方括号。 棘手的部分是class4。 sample1[1]不是一个位。位只在行末。

例子:

File1.txt
class1->Signal = sample1_sample2.sample3_sample4[4:4];
class2->Signal = sample1.sample2.sample3_sample4_sample5[2];
class3->Signal = sample1+sample2_sample3.sample4.sample5sample7[7:3];
class4->Signal = sample1[1]+sample2_sample3.sample4.sample5sample7[7:3];

期望结果:

class1 bit = [1:2]
class2 bit = [2]
class3 bit = [7:3]
class4 bit = [7:3]

我使用正则表达式,但方括号无法读取。 [] = 用于字符集。 ... = 除换行符外的任何字符。 参考:https://www.geeksforgeeks.org/perl-regex-cheat-sheet/

我的代码:

my $file = "$File1.txt";
my $line;

open (FILE,"<", $file) or die "Cannot open a file: $!";
while (<FILE>){
    my $line = $_;
    if ($line =~ m/[..]/){
        $line = $&;
    }
}
close (FILE);

只显示结果:.........

希望你们可以通过提供想法来帮助我。谢谢。


2
试试这个 https://regex101.com/r/NEcKF4/1 用 PCRE 正则表达式 ^([^-]*)->.*?(\[[^]]*\]); 一次,然后告诉我结果如何。干杯。 - RavinderSingh13
方括号在示例中是否始终出现在分号之前? - Destroy666
@Destroy666 是的。方括号中包含位始终在 ; 之前。但是单词中间也可能会有方括号。 - DM 256
2
perl -nE 'say "$1 bit = $2" if /(class\d+)->Signal.*(\[[:\d]+\])\s*;/' file.txt - jhnc
4个回答

4
请使用PCRE尝试以下正则表达式,根据您提供的示例。
^([^-]*)->.*?(\[[^]]*\]);$

这里是上面正则表达式的在线演示

解释:为上述正则表达式添加详细解释。

^            ##Matching from starting of the value here.
(            ##Creating 1st capturing group here.
  [^-]*      ##Matching everything before very next occurrence of - here.
)            ##Closing capturing group here.
->           ##Matching literal -> here.
.*?          ##Using lazy match to match till next occurrence of [ mentioned below.
(            ##Creating 2nd capturing group here.
  \[[^]]*    ##matching literal [ following by very first occurrence of ] here.
  \]         ##Matching literal ] here.
)            ##Closing 2nd capturing group here.
;$           ##Mentioning literal ; at the end of the value here.

3
嘿,老兄,一切都好吗?这个 .*? 不需要是非贪婪的,因为模式的最后一部分已经在字符串的末尾了。 - The fourth bird
3
@Thefourthbird,感谢上帝的恩典,我很好,你呢?是的,我知道这只是一个出现的情况,但考虑到它是PCRE,所以想使用懒惰匹配,干杯。 - RavinderSingh13
2
我同意 .*? 应该改为 .*,因为你已经有了结束锚点。 - anubhava

4

您可以选择要删除的部分,并用 bit = 替换。

^[^-]*\K->.*(?=\[[^][]*\];$)

解释

  • ^ 字符串开始
  • [^-]*\K 匹配除 - 以外的可选字符,并使用 \K 忘记到目前为止所匹配的内容
  • ->.* 匹配 -> 及其余部分
  • (?=\[[^][]*\];$) 正向先行断言,断言行末是 [...];

请查看 正则表达式演示Perl 演示

示例

use strict;
use warnings;

while (<DATA>)
{
  s/^[^-]*\K->.*(?=\[[^][]*\];$)/ bit = /;
  print $_;
}

__DATA__
class1->Signal = sample1_sample2.sample3_sample4[4:4];
class2->Signal = sample1.sample2.sample3_sample4_sample5[2];
class3->Signal = sample1+sample2_sample3.sample4.sample5sample7[7:3];
class4->Signal = sample1[1]+sample2_sample3.sample4.sample5sample7[7:3];

输出

class1 bit = [4:4];
class2 bit = [2];
class3 bit = [7:3];
class4 bit = [7:3];

或者更具体的正则表达式:

^class\d+\K->.*(?=\[[^][]*\];$)

查看另一个正则表达式演示


2

[..] 用于匹配方括号内的字符,这里是句点。

由于你只匹配字面上的句点,所以你只能看到这些。

这个问题可以通过一个相当简单的正则表达式来解决。

由于你只想要最后一个括号,你可以依靠 .* 的贪婪性跳过中间的任何括号:

use strict;
use warnings;

my $file = "File1.txt"; 
my $line;

open (FILE, "<", $file) or die "Cannot open a file: $!";
while (<FILE>){
    $line = $_;
    if( $line =~ /(class\d).*(\[[^\]]*\]);/ ){
        $line = "$1 bit = $2";
    }
}
close (FILE);

正则表达式/(class\d).*(\[[^\]]*\]);/将匹配以class开头的数字,然后.*匹配行的其余部分(因此它是贪婪的),并返回足够的内容来匹配(\[[^\]]*\]);

在字符文字中使用^作为第一个字符使其匹配除其中的字符之外的任何内容。要匹配文字[,必须像\[这样转义。

(              # capture to $1 
    class\d    # match "class" followed by a digit
)              # end capture
.*             # match anything (greedy)
(              # capture to $2
    \[         # literal [
    [^ \] ]*   # match anything, except ] (greedy)
    \]         # literal ]
)              # end capture
;              # match ;

括号将匹配到的内容保存到变量$1、$2等中。

使用相同的正则表达式和/r标志,也可以使用替换来完成此操作并返回值:

while (<FILE>){
    $line = s/(class\d).*(\[[^\]]*\]);/$1 bit = $2/r;
}

这是一个简单的命令行一行代码,可以做到同样的效果:
perl -wlp -e 's/(class\d).*(\[[^\]]*\]);/$1 bit = $2/' File1.txt

'更改为"以在Windows上运行


1
cat /tmp/a.txt
class1->Signal = sample1_sample2.sample3_sample4[4:4];
class2->Signal = sample1.sample2.sample3_sample4_sample5[2];
class3->Signal = sample1+sample2_sample3.sample4.sample5sample7[7:3];
class4->Signal = sample1[1]+sample2_sample3.sample4.sample5sample7[7:3];


sed -e 's/->.*\[/ bit = [/g' -e 's/;//g'  /tmp/a.txt
class1 bit = [4:4]
class2 bit = [2]
class3 bit = [7:3]
class4 bit = [7:3]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接