使用正则表达式修改 $self 中的属性

modifying attribute in $self using regex

我是 perl 的新手,我在修改 $self 中保存的属性时遇到问题。

我在 $self 中有一个名为 "devices" 的属性,如果我在 perl 调试器中打印它,它会像这样打印:

DB<22> x $self->{devices}
0  ARRAY(0xa1ec308)
0  "BG-SOKU-SAA01\cM\cJBG-SOKU-TS01 BG-SOKU-DCN01"

现在我想用逗号替换上述属性中的 \cM\cJ 和空格。所以我正在为它编写一个正则表达式,如下所示:

my @dM= @{$self->{devices}};
$dM[0]=~ s/\cM\cJ/,/g;
$dM[0]=~ s/ /,/g;

现在,当我打印 $self->{devices} 时,它给了我这个:

DB<22> x $self->{devices}
0  ARRAY(0xa1ec308)
0  'BG-SOKU-SAA01,BG-SOKU-TS01,BG-SOKU-DCN01'

RegEx 可以工作,但是当我将它传递给其他 class 并尝试对其进行迭代时,它会将逗号分隔的设备名称作为一个单一值,而不是每个设备名称都采用 1 个。

我不知道出了什么问题。

请帮我解决这个问题。

我认为您的问题是 $self -> {devices} 实际上是一个单元素数组 - 包含字符串 'BG-SOKU-SAA01,BG-SOKU-TS01,BG-SOKU-DCN01'

这意味着您希望它是一个数组 - 这通过 split

相对容易实现
@{$self -> {devices}} = map { split /,/ } @{$self -> {devices}} 

虽然您已经首先对定界符进行转换 - 您或许可以对其进行相同的操作。

@{$self -> {devices}} = map { split /(?:\cM\cJ|\s+)/ } @{$self -> {devices}}

map 是那些 "dark magic" perl 函数之一 - 它所做的是列表转换。

  • 我们采用源列表 - 在本例中 @{$self -> {devices}}
  • 应用代码块遍历它。 split /,/ - 这个 returns 零个或多个元素(我们用逗号分隔每个元素),它被添加到 new 列表中。
  • 然后我们分配新列表。

这与:

基本相同
my @new_list;

foreach my $element ( @{$self -> {devices}} ) {
    my @tmp = split /,/, $element;
    push ( @new_list, @tmp ); 
}

$self -> {devices} = \@new_list; 

第二个例子本质上是一样的,但是利用了split可以取正则表达式的事实。

通过使用:(?:\cM\cJ|\s+)

所以我们称:\cM\cJ 分隔符 \s+ 是 "one or more whitespace" 的正则表达式。这就是它处理制表符、换行符、多个空格等的原因。

注意 - 开头的 (?: 很重要,因为它表示一个非捕获组。如果您使用捕获(() 通常)那么这将是 'returned' 作为映射操作的一部分,因此您最终会得到一个不需要的元素 \cM\cJ 因为正则表达式捕获了它.

尝试掌握 Data::Dumper

use Data::Dumper;

然后

print Dumper $self;

这将帮助您了解对象的内容。