在Perl中如何提取字符串的一部分?

3
我是一名Perl的新手。我有一个字符串格式如下:
[ 时间戳 | 整数 | 字符串 ] 这里还有一些其他字符串 示例字符串:
[ 2013/05/28 21:39:02 | 2212 | MALFUNCTION  ] Please check for malfunction

timestamp是一个时间戳,例如:2013/05/28 20:38:02
整数是一个数字,字符串可以是一系列词语中的特定词语。
我想提取这个字符串部分。

Java中,我会简单地这样做:

String s = sentence.substring(line.lastIndexOf("|") + 1, line.lastIndexOf("]")).trim();  

这只是逐个字符循环字符串并获取感兴趣的部分。
但我不知道在Perl中如何解决这种“问题”。
我应该怎么做?只能通过正则表达式吗?

问题标题非常不清楚,无法理解你在问什么,你能改进一下吗? - undefined
@melwil: 这个版本好一点吗? - undefined
你能发布一个示例字符串吗? - undefined
关于正则表达式的一些基本问题,请查阅perldoc perlretut - undefined
5个回答

11
它并不一定非得使用正则表达式,但在Perl中是非常方便的:
my $str = "[ timestamp | integer | string ] Some other string here";
my ($timestamp, $integer, $string, $other)
   = ($str =~ /\[(.*?)\|(.*?)\|(.*?)\](.*)/);

好的,我明白了。答案片段中缺少最后一个斜杠/。但是$other是空的。 - undefined

7
您可以像Java一样操作它:
  • String.substringsubstr
  • String.lastIndexOfrindex
  • String.trimsub trim { my $s = $_[0]; $s =~ s/^\s+//; $s =~ s/\s+\z//; $s }
  • +.

但是这种方法只能找到最后一个|],而不能找到第二个及之后的。如果字符串中包含这些字符,则会失败。我建议使用:

my ($ts, $i, $s, $rest) =
   map trim($_),
      /^\[ ([^|]*) \| ([^|]*) \| ([^\]]*) \] (.*)/sx;

/^\[ ([^|]*) \| ([^|]*) \| ([^\]]*) \] .*/sx; 中,我假设第一个//sx 之前相当于括号?而 sx 是什么意思?这是如何工作的? - undefined
不,他们不是。它们是匹配运算符。 s使.匹配任何字符。 x允许您在模式中使用空格以提高可读性。 - undefined
但是 . 在正则表达式中匹配任何字符(除了换行符)的语法我不太理解。 - undefined
如果这是一个问题,也许答案在perlretut中可以找到。 - undefined

3

如果您要匹配的字符串不包含其他竖杠,您可以使用正则表达式:

$fullstring = '[ timestamp | integer | string ] Some other string here';
($string) = ($fullstring =~ /\| *([^|\]]*?) *]/);

这是如何工作的?我以为这个语法只会验证正则表达式是否包含在字符串中(=~表示匹配,/代替括号对,对吗?)。它还可以提取内容吗? - undefined
@Cratylus:当处于列表上下文时,它将返回捕获组。 - undefined

2

正则表达式是一种自然的 Perl 风格的处理方式。在这种情况下,我们想要最后一个 '|' 和第一个 ']' 之间的字符串,减去其中的任何周围空格。

my $string = ($line =~ m/
    \|  #The | character
    \s* #Arbitrary whitespace
    (   #Capture
        [^\|\]]*? #Some number of characters that are not | or ]
    )
    \s* #More whitespace
    \]  # The ] character
    /x)[0];

成语(m/(reg)ex/)[0]用于从正则表达式中提取第一个捕获组。否则,将返回捕获组的数组并转换为标量(数组的长度)。

在正则表达式上使用/x修饰符会忽略空格和#注释。

正则表达式中的*?标记意味着“非贪婪”匹配。否则,尾随的空格也会被捕获。


如果异常中不包含模式,捕获组数组的索引[0]会发生什么变化? - undefined
@Cratylus 如果是这样的话,那么匹配数组是空的。对于数组中不存在的索引值,其值为undef,所以$string也是undef - undefined

1
可以通过在|[]字符上分割行,然后去除提取的值的空格来解析行。
my @arr = map { s/^\s+ | \s+$//xg; $_ }  split / [\Q[]|\E] /x, $line;

之后,$arr[0]timestamp$arr[1]integer,以此类推。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接