2

文字列(数字を含む)を分割したい。以下の例では、文字列を k と k1 で分割します。

my @array1=("0","23","1","4","65","7");
$k=1;$k1=0;
my $j=join("",@array1);
my @ar=split(/($k|$k1)/,$j);
print join(";",@ar),"\n\n";

出力は;0;23;1;4657

上記の出力では、余分なセミコロン ";" 印刷中です

期待される出力は0;23;1;4657

以下の例で上記のコードを試すと、正しい出力が得られます(0;5;123;4;6)。余分なセミコロンはここでは印刷されません。

my @array1=("0","5","1234","6");
$k=5;$k1=4;

最初の例が余分なセミコロン「;」を出力している理由はわかりません。

これで誰かが私を助けることができますか?

4

5 に答える 5

2

違いは、最初の文字を分割すると、最初に空の値が得られることです。したがって、余分な; 0 の前 (および "" の後)。同様に ;; が見つかります。隣接する 2 つの文字で分割する場合

したがって、最も簡単な修正方法は、grep を使用して空の文字列を削除することです。

my @ar=split(/($k|$k1)/,$j);
@ar = grep /./, @ar;

これにより、@ar の空の文字列が削除されます。

全体像として、文字列を分割するためだけに文字列を結合している理由を確認したい場合があります。また、別の場所に表示される可能性のある番号を 1 つの場所に分割しています。$k=1 かつ @array1 = (11, 23, 1, 4); の場合と同様です。

于 2012-11-05T01:15:04.820 に答える
1

1 つのオプションは、の代わりに正規表現を使用することですsplit。これは、表示した両方のデータセットで機能します。

use strict;
use warnings;

my @array1 = ( "0", "23", "1", "4", "65", "7" );
my $k      = 1;
my $k1     = 0;

my $j      = join( '', @array1 );
my @ar = $j =~ /([$k$k1]|[^$k$k1]+)/g;
print join( ";", @ar );

出力:

0;23;1;4657
于 2012-11-05T02:27:49.480 に答える
1

これは非常に不自然な例であり、多くの問題があり (たとえば、$k と $k1 は "my" で宣言する必要がある、宣言する必要があるuse strictなど)、おそらく望ましくないことを実行するでしょう。

要するに、先頭のセミコロンが表示される理由は、文字列の先頭に一致する区切り文字で分割すると、分割によって空のリスト要素が返されるためです。

print join ';', split /0/, '0123';
于 2012-11-05T01:15:49.033 に答える
1

このコードには、私が気付いていなかった興味深い動作がいくつかあり、それは他の回答では明らかにされていません。split正規表現で通常起こることは、分割している文字が結果から省略されることです。ただし、正規表現で括弧をキャプチャすると、キャプチャされた素材が結果に保持されるようです。

脚本

#!/usr/bin/env perl

use strict;
use warnings;

my @array1 = ("0", "23", "1", "4", "65", "7");
my $j = join("", @array1);
my $k;
my $k1;
my @ar;
print "Join [$j]\n";

$k = 1;
$k1 = 0;
printf "%-25s", "Version 1 /($k|$k1)/:";
@ar = split(/($k|$k1)/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 2 /($k|$k1)/:";
$k = "1";
$k1 = "0";
@ar = split(/($k|$k1)/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 3 /[01]/:";
@ar = split(/[01]/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 4 /(0|1)/:";
@ar = split(/(0|1)/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 5 /0|1/:";
@ar = split(/0|1/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 6 /([46])/:";
@ar = split(/([46])/, $j);
print "[", join(";", @ar), "]\n";

printf "%-25s", "Version 7 /(?:[46])/:";
@ar = split(/(?:[46])/, $j);
print "[", join(";", @ar), "]\n";

出力

Join [02314657]
Version 1 /(1|0)/:       [;0;23;1;4657]
Version 2 /(1|0)/:       [;0;23;1;4657]
Version 3 /[01]/:        [;23;4657]
Version 4 /(0|1)/:       [;0;23;1;4657]
Version 5 /0|1/:         [;23;4657]
Version 6 /([46])/:      [0231;4;;6;57]
Version 7 /(?:[46])/:    [0231;;57]

ご覧のとおり、文字列が分割される正規表現にキャプチャ括弧が存在する場合、(キャプチャされた) 分割文字は保持されます。括弧が欠落しているか、明示的に非キャプチャ (バージョン 7) である場合、分割文字は保持されません。

また、マニュアルを注意深く読むと、split説明には次の段落が含まれています。

PATTERN に capture groups が含まれている場合、区切り文字ごとに、グループによってキャプチャされた各部分文字列に対して追加のフィールドが生成されます (グループが指定された順序で、後方参照に従ってグループが指定されます。いずれかのグループが一致しない場合は、undefまた、そのような追加のフィールドはセパレーターがある場合 (つまり、分割が発生した場合) に生成され、そのような追加のフィールドは LIMIT にはカウントされないことに注意してください。

いくつかの例が続きます。

Mac OS X 10.7.5 で Perl 5.16.0 を使用してテストしています。

于 2012-11-05T02:06:44.813 に答える
0

Perlは、この場合にsplit-fuと-fuを実行する必要をなくす、非常に強力な正規表現置換構造を提供します。join

$string =~ s{(?:$k|$k1)\K}{;}g ;
于 2012-11-05T11:36:42.980 に答える