【问题标题】:perl extract substrings between 2 delimitersperl 提取两个分隔符之间的子字符串
【发布时间】:2016-02-10 20:27:42
【问题描述】:

我有一个类似于下面的文件。

工作 |状态 |等待原因 |等待本地 |等待远程 |运行 |通过 |失败 |跳过 |失败 --------------------------------- -------- ---------- -- ----------- ------------ -------- -------- -------- - -------- --------- 构建 1 |失败 | | | | | 8 | 5 | | build2 ` |通过 | | | | | 2 | | | build3 |通过 | | | | | 6 | | |

我需要提取分隔符 '|' 之间的子字符串。我尝试使用下面的正则表达式

$row=~ s/ //g; (@substrings)= $row =~ /|(.*?)\|/g;

结果是

0 :
1 : build1
2 :
3 : FAILED
4 :
5 :
6 :
7 :
8 :
..

我也使用了拆分函数split '|',$row;,但它返回的数据为

b
u
i
l
d
1


|
F
..

我正在尝试提取以下数据。

$substrings[0]=build1
$substrings[1]=FAILED
$substrings[2]=(null) 

等等。

如何提取子串?

【问题讨论】:

  • 你忘记转义第一个管道|

标签: regex string perl string-split csv


【解决方案1】:

正如 Maddy 和 sebnukem 所提到的,拆分就是答案。仅使用正则表达式是可行的,但由于在行首和行尾缺少管道 (|),因此更加复杂。这是一个读取数据文件的脚本:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

foreach my $line (<>) {
#   print $line;
    chomp($line);
    next unless $line =~ /\|/; # only try lines with pipes in them
    my @fields = split(/\s+\|/,$line);
    print Dumper(\@fields);
}

这是一个运行它的例子:

chicks$ cat data.txt | ./proc_data.pl 
$VAR1 = [
          'Jobs',
          'Status',
          'Wait Reason',
          'Wait Local',
          'Wait Remote',
          'Running',
          'Passing',
          'Failing',
          'Skipped',
          'Failures '
        ];
$VAR1 = [
          'build1',
          'FAILED',
          '',
          '',
          '',
          '',
          '      8',
          '     5',
          '',
          '         '
        ];
$VAR1 = [
          'build2                `',
          'PASSED',
          '',
          '',
          '',
          '',
          '      2',
          '',
          '',
          '         '
        ];
$VAR1 = [
          'build3',
          'PASSED',
          '',
          '',
          '',
          '',
          '      6',
          '',
          '',
          '        '
        ];

请注意,split 将正则表达式放在斜杠中,而不是引号中,并且必须转义反斜杠:\|。我还包括一个\s+ 以从结果右侧修剪空格。正则表达式另一侧的\s+ 将获得左侧空格,如' 6'。如果您希望它匹配 0 个或多个空格,您应该在这些地方使用 * 而不是 +

【讨论】:

  • 这里没有用cat。当@ARGV 包含文件名列表时,菱形运算符会执行相同的操作。
  • \s+ 成功了。我试图匹配开始和结束并在两者之间提取字符串。
  • 另外,split() 的第一个参数绝对可以是字符串——事实上,空字符串 ('') 和包含单个空格的字符串有几种特殊情况(' ')。
【解决方案2】:

考虑使用拆分功能。以下是分隔符为空格的示例,您可以将其替换为“|”管道符号。

my $str = "ab cd ef gh ij";
my @words = split / /, $str;

【讨论】:

  • 这会将build1 | 转换为"build1", "", "", "", "", "", ...,每个空格对应一个字段。你想要' '——一个单一的文字空间。或/ +/,或/\s+/
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 2014-12-08
  • 2017-03-17
  • 2019-04-05
  • 2020-04-19
  • 2021-04-04
  • 2012-11-27
相关资源
最近更新 更多