我有一个字符串FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)
我想使用perl在找到A / D时将这些值存储在不同的数组中。
例如
Array1=1,10,A
Array2=11,20,D
Array3=31,5,BI,A
Array4=36,9,NU,D
Array5=46,9,D
不知道这一堆是3或4个值!
目前我正在使用split
#!/usr/bin/perl
use strict;
use warnings;
@main = "FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)";
my @val = split(/,/,$1);
print "Val Array = @val\n";
但如何进一步前进?
答案 0 :(得分:3)
# Grab the stuff inside the parens.
my $input = "FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)";
my ($vals_str) = $input =~ /\(([^)]+)\)/;
# Get substrings of interest.
my @groups = $vals_str =~ /[^,].+?,[AD](?=,|$)/g;
# Split those into your desired arrays.
my @forces = map [split /,/, $_], @groups;
请注意,这种基于正则表达式的方法适用于您可以认为输入数据相当干净的情况。如果您需要处理更混乱的数据并需要您的代码来执行验证,我建议您考虑不同的解析策略(如其他答案中所建议的那样)。
答案 1 :(得分:1)
my $str = 'FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)';
my ($list) = $str =~ /^[^=]*=\(([^()]*)\)$/
or die("Unexpected format");
my @list = split(/,/, $list);
my @forces;
while (@list) {
my @force;
while (1) {
die('No "A" or "D" value found') if !@list;
push @force, shift(@list);
last if $force[-1] eq 'A' || $force[-1] eq 'D';
}
push @forces, \@force;
}
结果:
@{$forces[0]} = ( 1, 10, 'A' );
@{$forces[1]} = ( 11, 20, 'D' );
@{$forces[2]} = ( 31, 5, 'BI', 'A' );
@{$forces[3]} = ( 36, 9, 'NU', 'D' );
@{$forces[4]} = ( 46, 9, 'D' );
答案 2 :(得分:1)
#!/usr/bin/perl
use strict;
use warnings;
use List::MoreUtils 'part';
# Grab the stuff inside the parens.
my $input = "FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)";
my ($vals_str) = $input =~ /\(([^)]+)\)/;
my @val = split(/,/,$vals_str);
print "Val Array = @val\n";
my $i = 0;
my @partitions = part { $_ eq 'A' || $_ eq 'D' ? $i++ : $i } @val;
创建一个数组@partitions
,其中每个元素都是对一个数组的引用,该数组包含您想要分组的3或4个元素。
答案 3 :(得分:1)
让我们从一些问题开始:
@main = "FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)";
您有use strict
,但首先您永远不会声明@main
,而@main
是一个数组,但您只需为其分配一个字符串。
my @val = split(/,/,$1);
$1
来自哪里?
print "Val Array = @val\n";
这实际上可行。如果@val
中有任何内容。
你有:
Array1=1,10,A
Array2=11,20,D
Array3=31,5,BI,A
Array4=36,9,NU,D
Array5=46,9,D
如您所期望的结果。这些标量变量,还是这些子数组?
我将假设以下内容:
FORCE
字符串转换为数组。因此,我将使用数组数组,这意味着我将使用References。
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
# Convert the string into an array
my $force = "FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)";
$force =~ s/FORCE=\((.*)\)/$1/; # Remove the "FORCE=(" prefix and the ")" suffix
my @main = split /,/, $force; # Convert string into an array
my @array_of_arrays; # Where I'm storing the arrays of arrays
my $array_of_arrays_number = 0; # Array number I'm using for @arrays
while (@main) { # Going through my "@main" array one character at a time
# Take a character from the @main array and put it onto whatever array of arrays you're pushing items into
my $character = shift @main;
push @{ $array_of_arrays[$array_of_arrays_number] }, $character;
# If Character is 'A' or 'D', start a new array_of_arrays
if ( $character eq 'A' or $character eq 'D' ) {
$array_of_arrays_number += 1;
}
}
# Let's print out these arrays
for my $array_number ( 0..$#array_of_arrays ) {
say "Array$array_number = ", join ", ", @{ $array_of_arrays[$array_number] };
}
答案 4 :(得分:0)
我喜欢功能方法,所以有一个版本首先制作拼接索引,然后生成子阵列数组
use strict;
use warnings;
use Carp;
sub splice_force ($) {
my $str = shift;
croak "Unexpected format" unless $str =~ /^FORCE=\(([^()]*)\)/;
my @list = split ',', $1;
# find end positions for each splice
my @ends = grep $list[$_] =~ /^[AD]$/, 0 .. $#list;
# make array with starting positions
my @starts = ( 0, map $_ + 1, @ends );
#finally make splices (ignore last @starts element so iterate by @ends)
map [ @list[ shift(@starts) .. $_ ] ], @ends;
}
my $str = 'FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)';
print "@$_\n" for splice_force $str;
答案 5 :(得分:0)
您可以在不创建中间数组的情况下执行此操作:
#!/usr/bin/env perl
use strict;
use warnings;
my $input = q{FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)};
my @groups = ([]);
while ($input =~ / ([A-Z0-9]+) ( [,)] ) /xg) {
my ($token, $sep) = ($1, $2);
push @{ $groups[-1] }, $token;
$token =~ /\A(?:A|D)\z/
or next;
$sep eq ')'
and last;
push @groups, [];
}
use YAML::XS;
print Dump \@groups;
输出:
--- - - '1' - '10' - A - - '11' - '20' - D - - '31' - '5' - BI - A - - '36' - '9' - NU - D - - '46' - '9' - D
答案 6 :(得分:0)
除了split
之外,不需要任何其他内容。此解决方案检查字符串是否具有预期形式,并提取括号之间的字符。然后将其拆分为逗号,前面是包含A
或D
的字段,结果将在逗号上再次拆分。
use strict;
use warnings;
use 5.014; # For \K regex pattern
my $str = 'FORCE=(1,10,A,11,20,D,31,5,BI,A,36,9,NU,D,46,9,D)';
my @parts;
if ( $str =~ /FORCE \s* = \s* \( ( [^)]+ ) \)/x ) {
@parts = map [ split /,/ ], split / [AD] [^,]* \K , /x, $1;
}
use Data::Dump;
dd \@parts;
<强>输出强>
[
[1, 10, "A"],
[11, 20, "D"],
[31, 5, "BI", "A"],
[36, 9, "NU", "D"],
[46, 9, "D"],
]