Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 在perl 5中更改标记和拆分之间的子组分隔符_Regex_Perl - Fatal编程技术网

Regex 在perl 5中更改标记和拆分之间的子组分隔符

Regex 在perl 5中更改标记和拆分之间的子组分隔符,regex,perl,Regex,Perl,我从文件中读取如下输入行: ewd1 n river2 n ne o u n <ewd8 ewd9 ewd2> se n ewd9 s n ewd2 sw 所以 @mydata =(' ','n','ewd8:ewd9:ewd2','se'); split可以很好地处理其他行,如: ewd1 n river2 n ne o u 但无法理解如何为更多的第三个参数行进行

我从文件中读取如下输入行:

ewd1    n   river2  n   ne  o   u
    n   <ewd8   ewd9    ewd2>   se
    n   ewd9    s
    n   ewd2    sw
所以

@mydata =(' ','n','ewd8:ewd9:ewd2','se');
split可以很好地处理其他行,如:

    ewd1    n   river2  n   ne  o   u
但无法理解如何为更多的第三个参数行进行分隔符替换和分组。有人有什么建议吗

下面是一个更完整的输入数据行示例:

ewd1    serpent 0   n   ne  o   u   w   nw  swamp
    bats    0   n   ne  o   u   w   nw  swamp
    undead  0   n   ne  o   u   w   nw  swamp
    n   river2  n   ne  o   u
    1002    e   d
    n   <ewd8   ewd9    ewd2>   se
    n   ewd9    s
    n   ewd2    sw
    n   rough   w   nw  swamp
ewd2    serpent 0   w   nw  n   swamp
    bats    0   w   nw  n   swamp
    undead  0   w   nw  n   swamp
    n   rough   w   nw  n   swamp
    n   <ewd1   ewd9    ewd10>  ne  o
    n   ewd9    e
    n   ewd10   se
    n   ewd4    s
    n   ewd3    sw
ewd1蛇0北东北西北沼泽
蝙蝠0 n ne o u w西北沼泽
不死生物0东北欧西北沼泽
北河
1002E-d
东南
n ewd9 s
n ewd2西南
n粗糙w西北沼泽
ewd2蛇0西西北北沼泽
蝙蝠0西北西北沼泽
不死生物0西北西北沼泽
n粗糙w西北n沼泽
n ne o
n ewd9 e
新南威尔士州东南部
n ewd4 s
n ewd3西南

字段将存储在perl中的结构化哈希表中。

如果每行始终有三个字段,则可以使用

/(<[^>]*>|\S+)\s+(<[^>]*>|\S+)\s+(<[^>]*>|\S+)/g
/(]*>|\S+)\S+(]*>|\S+)\S+(]*>|\S+)/g
或者,如果您有一个多行文本,并且第一个字段是可选的,并且如果有任何前导/尾随空格:

/^\h*(?:(<[^>]*>|\S+)\h+)?(<[^>]*>|\S+)\h+(<[^>]*>|\S+)\h*$/gm
/^\h*(?:(]*>\S+\h+)(]*>\S+\h+(]*>\S+)\h+(]*>\S+\h*$/gm

详细信息

  • ^
    -字符串/行的开头
  • \h*
    -0+水平空白
  • (?:(]*>|\S+\h+)
    -可选序列(第1组)
    或1+非空白字符,后跟1+水平空白字符
  • (]*>|\S+
    -第2组:
    或1+非空白字符
  • \h+
    -1+水平空白字符
  • (]*>|\S+
    -第3组:
    或1+非空白字符
  • \h*
    -0+水平空白字符
  • $
    -字符串/行的结尾

如果每行始终有三个字段,则可以使用

/(<[^>]*>|\S+)\s+(<[^>]*>|\S+)\s+(<[^>]*>|\S+)/g
/(]*>|\S+)\S+(]*>|\S+)\S+(]*>|\S+)/g
或者,如果您有一个多行文本,并且第一个字段是可选的,并且如果有任何前导/尾随空格:

/^\h*(?:(<[^>]*>|\S+)\h+)?(<[^>]*>|\S+)\h+(<[^>]*>|\S+)\h*$/gm
/^\h*(?:(]*>\S+\h+)(]*>\S+\h+(]*>\S+)\h+(]*>\S+\h*$/gm

详细信息

  • ^
    -字符串/行的开头
  • \h*
    -0+水平空白
  • (?:(]*>|\S+\h+)
    -可选序列(第1组)
    或1+非空白字符,后跟1+水平空白字符
  • (]*>|\S+
    -第2组:
    或1+非空白字符
  • \h+
    -1+水平空白字符
  • (]*>|\S+
    -第3组:
    或1+非空白字符
  • \h*
    -0+水平空白字符
  • $
    -字符串/行的结尾

最后,我以编程的方式完成了这项工作

首先,我将多元素字段分块,该字段可以位于尖括号或方括号之间:

if ($line =~ /(.+)(<|\[)(.+)(>|\])(.*)\s+/) { # joins multi destination elements together in one field
my $destination=join('|',split(/\s+/,$3));
$line=$1 . "\t" . $destination . "\t" . $5;
}

最后我按程序做了这件事

首先,我将多元素字段分块,该字段可以位于尖括号或方括号之间:

if ($line =~ /(.+)(<|\[)(.+)(>|\])(.*)\s+/) { # joins multi destination elements together in one field
my $destination=join('|',split(/\s+/,$3));
$line=$1 . "\t" . $destination . "\t" . $5;
}

您能显示预期的输出吗?匹配
/(]*>|\S+)\S+(]*>|\S+)\S+(]*>|\S+)/g
是否“n”始终是第一个值?你真的需要在你的字符串中找到那个部分吗?第二行中的项目是否始终为“ewd”?您需要最后一行的内容吗?第二行是否是唯一可能包含括号中多个项目的行?这些行的元素数不同,因此我看不出空格(
\s+
)如何作为分隔符,除非顺序无关紧要?那么,如何得到第一个元素,即空间呢?(这有可能是分开的吗?@WiktorStribiżew回答这个问题吗?但我认为第一个字段需要一个特例,看起来允许为空。您能显示预期的输出吗?与
/(]*>\S+)\S+(]*>\S+)\S+(]*>\S+)\S+(]*>\S+)/g
匹配“n”始终是第一个值吗?你真的需要在你的字符串中找到那个部分吗?第二行中的项目是否始终为“ewd”?您需要最后一行的内容吗?第二行是否是唯一可能包含括号中多个项目的行?这些行的元素数不同,因此我看不出空格(
\s+
)如何作为分隔符,除非顺序无关紧要?那么,如何得到第一个元素,即空间呢?(这有可能是分开的吗?@WiktorStribiżew回答这个问题吗?但我认为第一个字段需要一个特例,它看起来允许为空。为此,我最终选择了一个编码解决方案,而不仅仅是一个正则表达式,因为它变得有点复杂,因为独立元素的数量可变,而且每行的内容可能因行而异。@quentinnuk BTW,我看到你更新了这个问题。看起来你想要第一个非空白块,最后一个和中间的所有块,对吗?请尝试
/^\h*(]*>|\S+)\h+(.*)\h+(]*>|\S+)\h*$/gm
。检查一下,不完全正确。我希望所有内容都以空格分隔,作为带空格的单独字段,除非它在尖括号中,在这种情况下,我希望单个字段中尖括号之间的内容将该字段中的空格更改为(比如“:”,这样我就可以在整行中使用带空格分隔符的split,并将尖括号作为单个元素。谢谢,最后,我选择了一个编码解决方案,而不仅仅是一个正则表达式,因为它变得有点复杂,因为独立元素的数量可变,而且每行的内容可能因行而异。@quentinnuk顺便说一句,我看到你更新了这个问题。看起来你想要第一个非空白块,最后一个和中间的所有块,对吗?请尝试
/^\h*(]*>|\S+)\h+(.*)\h+(]*>|\S+)\h*$