我对这个问题有点晚了,但是我整理了一个更通用的解决方案:
# Similar to split() except pattern is applied backwards from the end of the string
# The only exception is that the pattern must be a precompiled regex (i.e. qr/pattern/)
# Example:
# rsplit(qr/:/, 'John:Smith:123:ABC', 3) => ('John:Smith', '123', 'ABC')
sub rsplit {
my $pattern = shift(@_); # Precompiled regex pattern (i.e. qr/pattern/)
my $expr = shift(@_); # String to split
my $limit = shift(@_); # Number of chunks to split into
# 1) Reverse the input string
# 2) split() it
# 3) Reverse split()'s result array element order
# 4) Reverse each string within the result array
map { scalar reverse($_) } reverse split(/$pattern/, scalar reverse($expr), $limit);
}
它接受类似于split()
的参数,只不过是以相反的顺序进行分割。如果需要指定结果元素的数量,它还接受限制子句。
注意:此子程序期望第一个参数为预编译正则表达式。
Perl的split
是内置的,并且会正确解释/pat/
,但尝试将/pat/
传递给子例程将被视为sub($_ =~ /pat/)
。
这个子程序并不是万无一失的!对于简单的分隔符,它足够好用,但更复杂的模式可能会引起问题。模式本身不能被反转,只能反转它匹配的表达式。
示例:
rsplit(qr/:/, 'One:Two:Three', 2); # => ('One:Two', 'Three')
rsplit(qr/:+/, 'One:Two::Three:::Four', 3); # => ('One:Two', 'Three', 'Four')
# Discards leading blank elements just like split() discards trailing blanks
rsplit(qr/:/, ':::foo:bar:baz'); # => ('foo', 'bar', 'baz')