2009-08-11 11 views
4

Repost from Perlmonksの場合:Perlのsplitコマンドと空白のトリミングを組み合わせるにはどうすればいいですか?

電子メールの長いリストをセミコロンで区切るためのperlスクリプトを作成しました。私がコードとしたいのは、分割を空白のトリミングと組み合わせるので、2つの配列は必要ありません。最初の配列を読み込んでいる間にトリミングする場所がありますか?出力はソートされた名前のリストです。おかげさまで

#!/pw/prod/svr4/bin/perl 
use warnings; 
use strict; 

my $file_data = 
    'Builder, Bob ;Stein, Franklin MSW; Boop, Elizabeth PHD Cc: Bear, 
+ Izzy'; 
my @email_list; 

$file_data =~ s/CC:/;/ig; 
$file_data =~ s/PHD//ig; 
$file_data =~ s/MSW//ig; 

my @tmp_data = split(/;/, $file_data); 

foreach my $entry (@tmp_data) { 
    $entry =~ s/^[ \t]+|[ \t]+$//g; 
    push(@email_list, $entry); 
} 

foreach my $name (sort(@email_list)) { 
    print "$name \n"; 
} 
+2

split/\ s *; \ s */$ file_data –

+0

あなたはunpack()も使うことができると思いますが、それなしであなたにソリューションを提供してください。 – Makis

答えて

10

同じ機能を使用して、両方の操作を一度に行う必要はありません。アクションを別々に実行する方がより明確になることがあります。すなわち、各素子のオフホワイトスペースを取り除く(およびその結果をソートする)、第一分割される:

@email_list = 
    sort(
     map { 
       s/\s*(\S+)\s*/\1/; $_ 
      } 
      split ';', $file_data 
    ); 

EDIT:同時にストリングの複数の部分をストリップする落とし穴につながることができ、例えば、を下の空白を「エリザベス(Elizabeth)」部分に残すことに関するシンナンの指摘。その名前が内部空白を持たないという前提でコードスニペットをコード化しました。これは実際には間違っていて、私が意識的に気付いていれば間違っていたことに気づきました。

@email_list = 
    sort(
     map { 
       s/^\s+//; # strip leading spaces 
       s/\s+$//; # strip trailing spaces 
       $_   # return the modified string 
      } 
      split ';', $file_data 
    ); 
+0

明らかにコメントに複数のスペースを入れることはできませんが、* Elizabeth *の後ろにスペースがあります。 –

+0

>最初... 2番目...非常に良い点!上の編集された応答。 – Ether

+0

+1訂正していただきありがとうございます。 –

11

あなたは、これはトリックを行います、最初と最後の要素をトリミングする必要がない場合:

@email_list = split /\s*;\s*/, $file_data; 

あなたが最初と最後の要素をトリミングする必要がない場合は、最初の$file_dataをトリム、上記の手順を繰り返します。 :-P

2

Chrisは提案したことを行うことができますが、$ file_dataの先頭と末尾のスペースは処理しません。あなたはこのようにこれらの処理を追加することができます

:また

$file_data =~ s/\A\s+|\s+\z//g; 

、第二の配列を使用することは必要ではなかったことに注意してください。これを確認してください:

my $file_data = 'Builder, Bob ;Stein, Franklin MSW; Boop, Elizabeth PHD Cc: Bear, Izzy'; 
my @email_list; 

$file_data =~ s/CC:/;/ig; 
$file_data =~ s/PHD//ig; 
$file_data =~ s/MSW//ig; 

my @tmp_data = split(/;/, $file_data); 

foreach my $entry (@tmp_data) { 
    $entry =~ s/^[ \t]+|[ \t]+$//g; 
} 

foreach my $name (sort(@tmp_data)) { 
    print "$name \n"; 
} 
-1

いくつかのマイナーシンタクスエラーを除いて、これは作業全体を行うはずです。ああ、リスト操作、あなたはどれくらい美しいですか?

print join (" \n", sort { $a <=> $b } map { s/^[ \t]+|[ \t]+$//g } split (/;/, $file_data)); 
+1

マップを返すとs ///の結果はあまり役に立ちません。マップ{s /...// g; $ _} – ysth

+0

あなたはおそらく数値ソートを意味しません。 – ysth

1
my @email_list = map { s/^[ \t]+|[ \t]+$//g; $_ } split /;/, $file_data; 

以上エレガント:以下のコードは、(読み取り可能な、またそれ以上)改善くらいです

use Algorithm::Loops "Filter"; 
my @email_list = Filter { s/^[ \t]+|[ \t]+$//g } split /;/, $file_data; 
0

マイターン:

my @fields = grep { $_ } split m/\s*(?:;|^|$)\s*/, $record; 

また、第一ストリップ最後の要素も同様です。そう

my @fields = split m/\s*(?:;|^|$)\s*/, $record; 
shift @fields unless $fields[0]; 

が最も確実な方法である、あなたはスペースがあることをを知ってが、それはそうではない場合

my (undef, @fields) = split m/\s*(?:;|^|$)\s*/, $record; 

作品:grepは、最初の要素を取り除くためにやり過ぎている場合それをやる。

1

FAQのHow do I strip blank space from the beginning/end of a string?を参照してください。今

@email_list = sort map { 
    s/^\s+//; s/\s+$//; $_ 
} split ';', $file_data; 

、音符もforループエイリアスアレイの各要素は、そう

@email_list = sort split ';', $file_data; 

for (@email_list) { 
    s/^\s+//; 
    s/\s+$//; 
} 

もうまくいくこと。

関連する問題