我的字符串
(champs1 (champs6 donnee_o donnee_f) [(champs2 [] (champs3 _YOJNJeyyyyyyB (champs4 donnee_x)) (debut 144825 25345) (fin 244102 40647)), (champs2 [] (champs3 _FuGNJeyyyyyyB (champs4 donnee_z)) (debut 796443 190570) (fin 145247 42663))] [] []).
(注释为可读性):
(champs1
(champs6 donnee_o donnee_f)
[(champs2 []
(champs3 _YOJNJeyyyyyyB (champs4 donnee_x))
(debut 144825 25345)
(fin 244102 40647)
),
(champs2 []
(champs3 _FuGNJeyyyyyyB (champs4 donnee_z))
(debut 796443 190570)
(fin 145247 42663)
)]
[]
[]
).
在上面的字符串中,我想分别用这些值替换整数值:
$moyLargRectNom, $moyHautRectNom, $moyLargRectNom,
$moyHautRectNom, $moyLargRectMat, $moyHautRectMat,
$moyLargRectMat, $moyHautRectMat
我要在字符串中替换8个值。
这是我的REGEX
$ligne =~ s{
(.*debut) \s\d+ \s\d+
(.*fin) \s\d+ \s\d+
(.*debut) \s\d+ \s\d+
(.*fin) \s\d+ \s\d+
(.*)
}{
$1 . $moyLargRectNom .
$2 . $moyHautRectNom .
$3 . $moyLargRectNom .
$4 . $moyHautRectNom .
$5 . $moyLargRectMat .
$6 . $moyHautRectMat .
$7 . $moyLargRectMat .
$8 . $moyHautRectMat .
$9
}xe;
它根本不替换值;有人可以帮我吗?谢谢。
答案 0 :(得分:1)
尝试这个尺寸:
my @numbers = ($moyLargRectNom, $moyHautRectNom, $moyLargRectNom, $moyHautRectNom, $moyLargRectMat, $moyHautRectMat, $moyLargRectMat, $moyHautRectMat);
my @temp = split / /, $ligne;
for(@temp) {
if(/^\W*\d\W*$/) {
my $num = shift @numbers;
s/\d+/$num/;
}
}
$ligne = join " ", @temp;
根据@temp
中的“字词”(大约),制作一个列表$ligne
。它会生成另一个列表@numbers
,它是您要在列表中替换的数字列表,按您希望它们替换的顺序排列。然后它一个接一个地经过@temp
,如果一个给定的元素是一个数字(即匹配正则表达式/^\W*\d\W*$/
,这意味着它没有单词字符(所以它不是“champs4”)并且至少有一个数字 - 除了“25346”之外,这将匹配“25346”),然后用@numbers
中的第一个值替换数字部分。现在我已经测试过,我可以向你保证这确实有效!
我相信使用map
可以实现更短的实施,但这对你来说效果会很好。
这种方法对您的方法的优势:
首先,这个解决方案是可扩展的。要用您的解决方案替换八个以上的数字,您需要编写一个新的正则表达式。要使用我的解决方案替换八个以上的数字,只需向@numbers
添加一些条目即可。此代码可以放入一个子程序,该子程序需要更改字符串以及要更改的数字列表,您不必担心它们是否传递了正确数量的数字,或者它们是否具有正确的格式。
其次,粗略一瞥就更容易理解了。只要您使用的正则表达式很难在视觉上解析。即使它有效,总有一天有人可能需要改变你的代码来做一些不同的事情。如果你使用一个巨大的正则表达式,重写器(也许你)将只是摇头,突出你的代码,然后按删除,然后编写新代码来执行它。有了这个,他们可以很容易地看到你的代码中发生了什么,如果他们需要对它进行修改,他们就可以。
第三,如果您想要在指定数量的替换品中进行硬编码,您也可以这样做:
my @numbers = ($moyLargRectNom, $moyHautRectNom, $moyLargRectNom, $moyHautRectNom, $moyLargRectMat, $moyHautRectMat, $moyLargRectMat, $moyHautRectMat);
my @temp = split / /, $ligne;
my $max_replacements = 8;
for(@temp) {
if(/^\W*\d\W*$/) {
my $num = shift @numbers;
s/\d+/$num/;
last unless --$max_replacements;
}
}
$ligne = join " ", @temp;
作为旁注(之前已应用,但仍然适用),这将失败浮点数 - /^\W*\d\W*$/
将匹配浮点数,但s/\d+/$num/
不会替换浮点数,只有整数部分。如果您发现需要浮点数,请更改以下行:
s/\d+/$num/;
对此:
s/\d+|(?:\d+)?\.\d+/$num/;
那应该匹配浮点数。
答案 1 :(得分:1)
#!/usr/bin/perl
use strict;
use warnings;
my $s = <<EO_TXT;
(champs1 (champs6 donnee_o donnee_f) [(champs2 []
(champs3 _YOJNJeyyyyyyB (champs4 donnee_x)) (debut 144825 25345)
(fin 244102 40647)), (champs2 [] (champs3 _FuGNJeyyyyyyB
(champs4 donnee_z)) (debut 796443 190570) (fin 145247 42663))] [] []).
EO_TXT
my (
$moyLargRectNom, $moyHautRectNom,
$moyLargRectMat, $moyHautRectMat,
) = map { "val$_" } qw( 1 2 3 4 );
my @replacements = (
$moyLargRectNom, $moyHautRectNom,
$moyLargRectNom, $moyHautRectNom,
$moyLargRectMat, $moyHautRectMat,
$moyLargRectMat, $moyHautRectMat,
);
$s =~ s/\b[0-9]+\b/%s/g; # replace %s with the appropriate specifier
$s = sprintf $s, @replacements;
print $s, "\n";
答案 2 :(得分:0)
你似乎以与我相反的方式这样做。即我会查找这些数字并替换它们,而不是替换它们,即匹配数字周围的东西并将它们代入字符串。
总是会有8个值吗?他们会一直跟着同样的话吗?如果是的话:
.+?debut\s([\d]+)\s([\d]+).+?fin\s([\d]+)\s([\d]+).+?debut\s([\d]+)\s([\d]+).+?fin\s([\d]+)\s([\d]+)
或者可以首次亮相&amp; fin出现在任何地方,无论什么时候你都想要替换它们:
首次亮相x y - &gt;首次亮相$ moyLargRectNom,$ moyHautRectNom, fin x y - &gt; fin $ moyLargRectNom,$ moyHautRectNom, (首次亮相144825 25345)(fin 244102 40647)
如果这是真的,只需使用两个简单的正则表达式:
debut\s([\d]+)\s([\d]+)
fin\s([\d]+)\s([\d]+)
并用单词..
替换组但我不记得哪个变量存储了创建的组数,抱歉。
答案 3 :(得分:0)
我认为你的结构太不规则或奇怪,不适合正则表达式,嵌套表达式很少。
所以我去寻找一张解析树。找不到适合的,不理解任何正式的解析语法,我写了自己的令牌/状态机。
它将您的代码转换为数据树,然后您可以使用简单的循环结构提取它。
谨防,代码仅设计用于您目前提供的小型数据集,不平衡的括号会给解析器带来麻烦并产生无用的树。
浏览到底部以了解如何使用此blob
#!/usr/bin/perl
use strict;
use warnings;
use version;
use Data::Dumper;
our $VERSION = qv('0.1');
my @stack;
my $data = <<'EOF';
(champs1
(champs6 donnee_o donnee_f)
[(champs2 []
(champs3 _YOJNJeyyyyyyB (champs4 donnee_x))
(debut 144825 25345)
(fin 244102 40647)
),
(champs2 []
(champs3 _FuGNJeyyyyyyB (champs4 donnee_z))
(debut 796443 190570)
(fin 145247 42663)
)]
[]
[]
)
EOF
push @stack,
{
tokens => [],
context => 'void',
};
my $state;
my $eaten;
my $str = $data;
sub eat
{
my $n = shift;
substr( $str, 0, $n, '' );
}
while ( @stack && $str )
{
$state = $stack[-1];
my @tokens = @{ $stack[-1]->{tokens} };
my $context = $stack[-1]->{context};
if ( $str =~ m{(^[\s,]+)} )
{
eat length($1);
next;
}
if ( $str =~ m{(^\w+)} )
{
eat length($1);
push @{ $stack[-1]->{tokens} }, $1;
next;
}
if ( $str =~ m{^\[}
and $context eq 'nest'
|| $context eq 'nestgroup'
|| $context eq 'array' )
{
eat 1;
print "\e[33m[\e[0m";
push @stack,
{
tokens => [],
context => 'array',
};
next;
}
if ( $str =~ m{^\]} and $context eq 'array' )
{
eat 1;
print "\e[33m]\e[0m";
pop @stack;
push @{ $stack[-1]->{tokens} }, \@tokens;
next;
}
if (
$str =~ m{^\((champs(\d)|debut|fin)\s}
and ( $context eq 'nest'
|| $context eq 'array'
|| $context eq 'nestgroup'
|| $context eq 'void' )
)
{
eat length($1) + 1;
$stack[-1]->{nodename} = $1;
print "\e[32m($1\e[0m";
push @stack,
{
tokens => [],
context => 'nestgroup',
};
next;
}
if ( $str =~ m{^\)} and $context eq 'nestgroup' )
{
eat 1;
print "\e[32m)\e[0m";
pop @stack;
my $nodename = $stack[-1]->{nodename};
push @{ $stack[-1]->{tokens} }, { $nodename, \@tokens };
next;
}
if ( $str =~ m{^\(} )
{
eat 1;
print "\e[31m(\e[0m";
push @stack,
{
tokens => [],
context => 'nest',
};
next;
}
if ( $str =~ m{^\)} and $context eq 'nest' )
{
eat 1;
print "\e[31m)\e[0m";
pop @stack;
push @{ $stack[-1]->{tokens} }, \@tokens;
next;
}
print substr( $str, 0, 1 ), "\e[34m$context\e[0m";
eat 1;
}
$Data::Dumper::Indent = 1;
$Data::Dumper::Terse = 1;
print "Tree:\n";
print Dumper( $state->{tokens}->[0]->{champs1}->[1] );
print "--------";
for ( @{ $state->{tokens}->[0]->{champs1}->[1] } )
{
my @data = @{ $_->{champs2} };
print ">", Dumper( $data[2], $data[3] );
}
输出:
(champs1(champs6)[(champs2[](champs3(champs4))(debut)(fin))(champs2[](champs3(champs4))(debut)(fin))][][])
Tree:
[
{
'champs2' => [
[],
{
'champs3' => [
'_YOJNJeyyyyyyB',
{
'champs4' => [
'donnee_x'
]
}
]
},
{
'debut' => [
'144825',
'25345'
]
},
{
'fin' => [
'244102',
'40647'
]
}
]
},
{
'champs2' => [
[],
{
'champs3' => [
'_FuGNJeyyyyyyB',
{
'champs4' => [
'donnee_z'
]
}
]
},
{
'debut' => [
'796443',
'190570'
]
},
{
'fin' => [
'145247',
'42663'
]
}
]
}
]
--------
>{
'debut' => [
'144825',
'25345'
]
}
{
'fin' => [
'244102',
'40647'
]
}
>{
'debut' => [
'796443',
'190570'
]
}
{
'fin' => [
'145247',
'42663'
]
}