【问题标题】:Extract data between square brackets "[]" using Perl使用 Perl 提取方括号“[]”之间的数据
【发布时间】:2014-07-22 08:44:31
【问题描述】:

我使用正则表达式从弯括号(或“括号”)中提取数据,例如从(a,b) 中提取a,b,如下所示。我有一个文件,其中每一行都像

this is the range of values (a1,b1) and [b1|a1]
this is the range of values (a2,b2) and [b2|a2]
this is the range of values (a3,b3) and [b3|a3]

我正在使用以下字符串来提取a1,b1a2,b2 等...

@numbers = $_ =~ /\((.*),(.*)\)/

但是,如果我想从方括号[] 中提取数据,我该怎么做呢?例如

this is the range of values (a1,b1) and [b1|a1]
this is the range of values (a1,b1) and [b2|a2]

我只需要提取/匹配方括号中的数据,而不是弯括号。

【问题讨论】:

  • 只需使用@numbers = $_ =~ /[(.*),(.*)]/
  • @Jens @Naidu:请不要只使用那个模式。您将强制引擎进行大量不必要的回溯。 .* 几乎从来都不是你真正想要的。

标签: regex perl non-greedy


【解决方案1】:

我知道我在这里有点晚了,但没有一个答案正确回答了 OP 的问题,而与方括号 [] 一起真正匹配整个问题的答案。显然,OP 想要匹配括号内的内容。

  • 匹配方括号内的所有内容以及括号。 Example

    \[[^\[\]]*]

  • 要匹配方括号内的所有内容,不包括括号本身,请使用 积极的前瞻和后视。 Example

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

【讨论】:

    【解决方案2】:

    使用下面的代码

    $_ =~ /\[(.*?)\|(.*?)\]/g;
    

    现在如果模式匹配成功,提取的值将存储在$1$2 .

    【讨论】:

      【解决方案3】:

      [更新]同时,我写了一篇关于.*的具体问题的博文,我在下面描述:Why Using .* in Regular Expressions Is Almost Never What You Actually Want


      如果您的标识符a1b1 等本身从不包含逗号或方括号,则应使用以下模式以避免回溯地狱:

      /\[([^,\]]+),([^,\]]+)\]/
      

      这是working example on Regex101

      .* 这样的贪婪量词的问题在于,您很可能在开始时消耗太多,因此正则表达式引擎必须进行大量回溯。即使您使用非贪婪量词,引擎也会进行比必要更多的匹配尝试,因为它一次只会消耗一个字符,然后尝试推进模式中的位置。

      (您甚至可以使用atomic groups 使匹配更加高效。)

      【讨论】:

      • @marius 我试过使用你的模式,但我有一个问题,比如我有这条线,因为这是再次使用你的模式时的值范围 (a1,b1) [b1,a1] 它的提取曲括号之间的数据,但我需要提取或匹配方括号中的数据
      • @Naidu 实际上这不应该发生,因为我明确匹配(转义)方括号:\[。您是否确保将模式正确嵌入到代码中?
      • @Naidu 我刚刚添加了一个工作示例的链接,请参阅我更新的帖子。
      • @marius 是的,我已经正确添加了模式,即使它给出了相同的概率,我已经更新了问题你是否检查了这条线,因为其中会有弯括号和方括号跨度>
      • @Naidu 我确实检查过,我的模式对我来说非常好。您是否查看了我发布的示例的链接?
      【解决方案4】:

      你可以使用非贪心量词*?来匹配它

      my @numbers = $_ =~ /\[(.*?),(.*?)\]/g;
      

      my @numbers = /\[(.*?),(.*?)\]/g;
      

      简称。

      更新

      my @numbers = /\[(.*?)\|(.*?)\]/g;
      

      【讨论】:

      • 他说的是括号。
      • 嗨,mpapec 我在我的问题的早期没有提到一件事,即当我使用匹配模式时也有曲括号,它不识别方括号,而是匹配曲括号并从中提取数据请问你能帮我解决这个问题吗?
      • 输入将是这是值的范围 (a1,b1) 和 [b1|a1] 这是值的范围 (a2,b2) 和 [b2|a2] 这是范围我需要将值 (a3,b3) 和 [b3|a3] 输出为 b1 a1 b2 a2 b3 a3,即只有方括号中的数据应该被匹配和提取
      • @mpapec 我早些时候尝试了更新,但它没有帮助 dono 为什么
      【解决方案5】:
      #!/usr/bin/perl
      # your code goes here
      my @numbers;
      while(chomp(my $line=<DATA>)){
          if($line =~ m|\[(.*),(.*)\]|){
          push @numbers, ($1,$2);
          }
      }
      print @numbers; 
      __DATA__
      this is the range of values [a1,b1]
      this is the range of values [a2,b2]
      this is the range of values [a3,b3]
      

      Demo

      【讨论】:

      • 恐怕这不是一个很好的解决方案,因为使用.* 会导致回溯地狱。请参考我上面的回答和cmets。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 2018-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多