在Perl中将字符串拆分为数组

15
my $line = "file1.gz file2.gz file3.gz";
my @abc = split('', $line);
print "@abc\n";

期望输出:

file1.gz
file2.gz
file3.gz
我希望输出在$abc[0]中为file1.gz,在$abc[1]中为file2.gz,在$abc[2]中为file3.gz。我应该如何拆分$line

1
好的,没有一种编程语言可以读取你的思想。split ''会将字符串分割成单个字符。如果你所有的文件名都以 file... 开头,那么 split /(?=file)/ 就可以工作了,但是并没有通用的解决方案。 - amon
2
@aragaer 你的评论事实上是错误的。split 接受模式、字符串和限制作为参数。你的顺序是错误的。而且,只要 $" 等于 "\n"(通常情况下 $" 是一个空格),print "@abc\n" 就可以正常工作。 - amon
5个回答

22

通过空格分割字符串非常简单:

print $_, "\n" for split ' ', 'file1.gz file1.gz file3.gz';

这实际上是split的一个特殊形式(因为此函数通常接受模式而不是字符串):

作为另一个特殊情况,当PATTERN被省略或由单个空格字符组成的字面字符串(如' '"\x20")时,split模仿命令行工具awk的默认行为。在这种情况下,在分割发生之前,将删除EXPR中的任何前导空格,并将PATTERN视为/\s+/,这意味着任何连续的空格(而不仅仅是单个空格字符)都用作分隔符。


以下是针对原问题(使用简单字符串且没有任何空格)的答案:

也许您想要按.gz扩展名进行拆分:

my $line = "file1.gzfile1.gzfile3.gz";
my @abc = split /(?<=\.gz)/, $line;
print $_, "\n" for @abc;

在这里我使用了(?<=...)构造,它是后向断言,基本上是在每个以.gz子字符串为前缀的位置分割行。

如果您使用固定的扩展名集合,可以扩展模式以包含所有扩展名:

my $line = "file1.gzfile2.txtfile2.gzfile3.xls";
my @exts = ('txt', 'xls', 'gz');
my $patt = join '|', map { '(?<=\.' . $_ . ')' } @exts;
my @abc = split /$patt/, $line;
print $_, "\n" for @abc;

问题已更改以包括空格 - jamylak
@user2384801 添加了解释和链接。 - raina77ow

14

现在有$line这个字符串,你可以根据至少一个空格分隔符来简单地将其拆分。

my @answer = split(' ', $line); # creates an @answer array

然后

print("@answer\n");               # print array on one line
或者
print("$_\n") for (@answer);      # print each element on one line

我更喜欢使用()来进行splitprintfor操作。


2
你应该知道,默认的 ' ' 分隔符可能是你想要的,而不是 /\s+/。它们完全相同,只是默认的分隔符在分割之前会去除前导空格。 - TLP
1
@TLP 非常感谢 - 我一直使用 /\s+/ 忽略默认的 ' '。我仍然觉得 /\s+/ 更容易理解,因为它做了它所显示的事情...但我猜 ' ' 更容易记住,确切地做到了我们想要的(通常没有人关心第一个元素是一个 0 字符串),并且肯定经过了优化,不需要昂贵的正则表达式。回答已更新。 - Déjà vu

2
只需使用 /\s+/ 作为分隔符即可将空格去除。通常情况下,这种行为是必要的。因此,在您的情况下,应该是这样的:
my $line = "file1.gz file1.gz file3.gz";
my @abc = split(/\s+/, $line);

0

我觉得这个很简单!

my $line = "file1.gz file2.gz file3.gz";

my @abc =  ($line =~ /(\w+[.]\w+)/g);

print $abc[0],"\n";
print $abc[1],"\n";
print $abc[2],"\n";

输出:

file1.gz 
file2.gz 
file3.gz

请看一下这个教程,了解更多关于Perl正则表达式的内容,并向下滚动到更多匹配部分。


0

您已经有多个关于您问题的答案了,但我想在这里添加另一个小细节,希望能够帮助您添加一些内容。

要查看Perl中的数据结构,可以使用 Data::Dumper。要打印字符串,可以使用 say,它在每次调用后自动添加换行符"\n"而不是显式添加。

我通常使用\s来匹配空白字符。如果添加+,则匹配一个或多个空白字符。您可以在此处阅读更多信息perlre

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

use feature 'say';

my $line = "file1.gz file2.gz file3.gz";
my @abc  = split /\s+/, $line;

print Dumper \@abc;
say for @abc;

有人降低此答案的原因吗?根据来自 Perl::doc 的官方文档:“在这种情况下,在拆分发生之前将删除 EXPR 中的任何前导空格,并且 PATTERN 被视为 /\s+/,特别是这意味着任何连续的空格(不仅仅是一个空格字符)都用作分隔符。” - Thanos

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