使用正则表达式提取字符串的一部分

时间:2015-08-23 08:24:05

标签: regex perl

我有一个带有模式的文本文件,如下所示。

  

“S | O | M |百灵| N | K | V | A |升| U | E | S | CAP1 {捕获|这些|值} | S | O | M |百灵| N | K | V | A |升| U | E | S | CAP2 [捕获|这些|值] | S | O | M |百灵| N | K | v | A |升| U | E | S | CAP3 {[捕获|这些|值] | [捕获|这些|值]}“

我正在尝试提取值 cap1 cap2 CAP3

我正在尝试使用正则表达式"([a-z]|[|])cap1(\{(.*?)\})([a-z]|[|]|[0-9])",但没有运气,任何帮助都会受到赞赏。

3 个答案:

答案 0 :(得分:1)

据我所知,你想逐一提取cap1,cap2,CAP3的值。那么有3个正则表达式

cap1

cap1\{([^\}]*)\}

<强>解释

cap1\{匹配文字cap1{

([^\}]*)}以外的任何字符捕获到组$1

\}匹配文字}

cap2

cap2\[([^\]]*)\]

<强>解释

cap2\[匹配文字cap2[

([^\]]*)]以外的任何字符捕获到组$1

\]匹配文字]

CAP3

CAP3\{\[([^\]]*)\]\|\[([^\]]*)\]\}

<强>解释

CAP3\{匹配文字CAP3{

\[([^\]]*)\]\|\[([^\]]*)\]]以外的任何字符分别捕获到群组$1$2

\}匹配文字}

补充:感谢@Borodin发表评论,要完成此任务,您不需要使用环视,但如果您想进行搜索和替换,可能需要环视

cap1(?<=cap1\{)([^\}]*)(?=\})

cap2(?<=cap2\[)([^\]]*)(?=\])

CAP3(?<=CAP3\{)\[([^\]]*)\]\|\[([^\]]*)\](?=\})

答案 1 :(得分:0)

使用这样的模式应该有效:

[{\[]+([^}{\]\[]+)[\]}]+

<强>代码

$searchText =~ m/[{\[]+([^}{\]\[]+)[\]}]+/

示例

https://regex101.com/r/qI3fI6/1

答案 2 :(得分:0)

更新

我道歉 - 我最初将你的问题误认为是一件更为琐碎的事情

基本上,您希望对管道split字符执行|,不包括括号或大括号[ ... ]{ ... }对中的字符。只要你不需要考虑相同类型的括号内的嵌套(即括号只包含括号,括号只会包含括号),那么它就像这样完成

my @matches = $s =~ m{ \w+ ( \{ [^{}]* \} | \[ [^\[\]]* \] ) }gx;
print "$_\n" for @matches;

输出

{capture|these|values}
[capture|these|values]
{[capture|these|values]|[capture|these|values]}

您显示的数据没有包含大括号的括号或包含括号的括号,但我怀疑对数据嵌套没有理论限制,在这种情况下需要进行一些递归

下面程序中的正则表达式模式定义了里面一对匹配括号中的文本,作为管道分隔的序列

  • 另一对匹配括号及其内容[ ... ]
  • 另一对匹配大括号及其内容{ ... }
  • 一系列字符,例如capturevalues

第二对捕获括号内的模式匹配。它是一种递归模式,使用相对编号(?-1)来调用自身。这也可以是绝对编号(?2)但如果前面的捕获数量发生变化则必须更改

完整模式在递归模式之前查找并捕获一系列单词字符,以便考虑cap1cap2等。这样可以将glolbal搜索的结果直接分配给结果显示在下面的哈希

use strict;
use warnings;

my $s = "s|o|m|j|n|k|v|a|l|u|e|s|cap1{capture|these|values}|s|o|m|j|n|k|v|a|l|u|e|s|cap2[capture|these|values]|s|o|m|j|n|k|v|a|l|u|e|s|CAP3{[capture|these|values]|[capture|these|values]}";

my %captures = $s =~ m{
    ( (?> \w+ ) )
    (
        \{ (?-1) (?> \| (?-1) )* \} |
        \[ (?-1) (?> \| (?-1) )* \] |
        \w+
    )
}gx;

use Data::Dump;
dd \%captures;

输出

{
  cap1 => "{capture|these|values}",
  cap2 => "[capture|these|values]",
  CAP3 => "{[capture|these|values]|[capture|these|values]}",
}


原始答案

看起来您希望所有标识符前面都有一个竖线|字符,后跟方括号或大括号[{

这个程序会为你做到这一点

use strict;
use warnings;
use v5.10;

my $s = "s|o|m|j|n|k|v|a|l|u|e|s|cap1{capture|these|values}|s|o|m|j|n|k|v|a|l|u|e|s|cap2[capture|these|values]|s|o|m|j|n|k|v|a|l|u|e|s|CAP3{[capture|these|values]|[capture|these|values]}";

for ( $s ) {
    my @captures = /\|(\w+)[\[\{]/g;
    say for @captures;
}

输出

cap1
cap2
CAP3