使用键中的特殊字符进行Perl哈希替换

时间:2022-11-17 16:51:32

My current script will take an expression, ex:

我当前的脚本将采用表达式,例如:

my $expression = '( a || b || c )';

and go through each boolean combination of inputs using sub/replace, like so:

并使用sub / replace遍历每个布尔输入组合,如下所示:

my $keys = join '|', keys %stimhash;
$expression =~ s/($keys)\b/$stimhash{$1}/g;

So for example expression may hold,

所以例如表达可能成立,

( 0 || 1 || 0 )

This works great.

这很好用。

However, I would like to allow the variables (also in %stimhash) to contain a tag, *.

但是,我想允许变量(也在%stimhash中)包含标记*。

my $expression = '( a* || b* || c* )';

Also, printing the keys of the stimhash returns:

此外,打印刺激的键返回:

a*|b*|c*

It is not properly substituting/replacing with the extra special character, *.
It gives this warning:

它没有用额外的特殊字符*替换/替换。它给出了这个警告:

Use of uninitialized value within %stimhash in substitution iterator

在替换迭代器中使用%stimhash中的未初始化值

I tried using quotemeta() but did not have good results so far.
It will drop the values. An example after the substitution looks like:

我尝试使用quotemeta()但到目前为止没有很好的结果。它会降低价值。替换后的示例如下:

( * || * || * )

Any suggestions are appreciated,

任何建议表示赞赏,

John

约翰

1 个解决方案

#1


1  

Problem 1

You use the pattern a* thinking it will match only a*, but a* means "0 or more a". You can use quotemeta to convert text into a regex pattern that matches that text.

您使用模式a *认为它只匹配*,但a *表示“0或更多a”。您可以使用quotemeta将文本转换为与该文本匹配的正则表达式模式。

Replace

更换

my $keys = join '|', keys %stimhash;

with

my $keys = join '|', map quotemeta, keys %stimhash;

Problem 2

\b

is basically

基本上是

(?<!\w)(?=\w)|(?<=\w)(?!\w)

But * (like the space) isn't a word character. The solution might be to replace

但是*(就像空格一样)不是一个单词字符。解决方案可能是替换

s/($keys)\b/$stimhash{$1}/g

with

s/($keys)(?![\w*])/$stimhash{$1}/g

though the following make more sense to me

虽然以下对我来说更有意义

s/(?<![\w*])($keys)(?![\w*])/$stimhash{$1}/g

Personally, I'd use

就个人而言,我会用

s{([\w*]+)}{ $stimhash{$1} // $1 }eg

#1


1  

Problem 1

You use the pattern a* thinking it will match only a*, but a* means "0 or more a". You can use quotemeta to convert text into a regex pattern that matches that text.

您使用模式a *认为它只匹配*,但a *表示“0或更多a”。您可以使用quotemeta将文本转换为与该文本匹配的正则表达式模式。

Replace

更换

my $keys = join '|', keys %stimhash;

with

my $keys = join '|', map quotemeta, keys %stimhash;

Problem 2

\b

is basically

基本上是

(?<!\w)(?=\w)|(?<=\w)(?!\w)

But * (like the space) isn't a word character. The solution might be to replace

但是*(就像空格一样)不是一个单词字符。解决方案可能是替换

s/($keys)\b/$stimhash{$1}/g

with

s/($keys)(?![\w*])/$stimhash{$1}/g

though the following make more sense to me

虽然以下对我来说更有意义

s/(?<![\w*])($keys)(?![\w*])/$stimhash{$1}/g

Personally, I'd use

就个人而言,我会用

s{([\w*]+)}{ $stimhash{$1} // $1 }eg