Split a string into array in Perl

2020-05-28 08:38发布

问题:

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

Expected output:

file1.gz
file2.gz
file3.gz

I want the output to be file1.gz in $abc[0], file2.gz in $abc[1], and file3.gz in $abc[2]. How do I split $line?

回答1:

Splitting a string by whitespace is very simple:

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

This is a special form of split actually (as this function usually takes patterns instead of strings):

As another special case, split emulates the default behavior of the command line tool awk when the PATTERN is either omitted or a literal string composed of a single space character (such as ' ' or "\x20"). In this case, any leading whitespace in EXPR is removed before splitting occurs, and the PATTERN is instead treated as if it were /\s+/; in particular, this means that any contiguous whitespace (not just a single space character) is used as a separator.


Here's an answer for the original question (with a simple string without any whitespace):

Perhaps you want to split on .gz extension:

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

Here I used (?<=...) construct, which is look-behind assertion, basically making split at each point in the line preceded by .gz substring.

If you work with the fixed set of extensions, you can extend the pattern to include them all:

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;


回答2:

Having $line as it is now, you can simply split the string based on at least one whitespace separator

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

then

print("@answer\n");               # print array on one line

or

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

I prefer using () for split, print and for.



回答3:

I found this one to be very simple!

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";

output:

file1.gz 
file2.gz 
file3.gz

Here take a look at this tutorial to find more on Perl regular expression and scroll down to More matching section.



回答4:

You already have multiple answers to your question, but I would like to add another minor one here that might help to add something.

To view data structures in Perl you can use Data::Dumper. To print a string you can use say, which adds a newline character "\n" after every call instead of adding it explicitly.

I usually use \s which matches a whitespace character. If you add + it matches one or more whitespace characters. You can read more about it here 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;


回答5:

Just use /\s+/ against '' as a splitter. In this case all "extra" blanks were removed. Usually this particular behaviour is required. So, in you case it will be:

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