2010-03-17 3 views
5

aşağıdaki biçimde metni içeren bir dize bölme için bir çözüm arayan kulüpler:Tek tırnaklı bir dizenin dışında bir dizgeyi boşluklarla nasıl bölebilirim?

aşağıdaki sonuçları üretecektir
"abcd efgh 'ijklm no pqrs' tuv" 

: Başka bir deyişle

['abcd', 'efgh', 'ijklm no pqrs', 'tuv'] 

, bu boşluk sürece tarafından böler tek bir alıntı dizenin içinde. Ben özellikle "Dengeleme" operatörleri kullanarak .NET regexps ile yapılabilir, özellikle dengeleme operatörleri. Perl'den pek emin değilim.

cevap

15

Kullanım Text::ParseWords:

#!/usr/bin/perl 

use strict; use warnings; 
use Text::ParseWords; 

my @words = parse_line('\s+', 0, "abcd efgh 'ijklm no pqrs' tuv"); 

use Data::Dumper; 
print Dumper \@words; 

Çıktı:

C:\Temp> ff 
$VAR1 = [ 
      'abcd', 
      'efgh', 
      'ijklm no pqrs', 
      'tuv' 
     ];

Kullanılan desen görmek Text::ParseWords::parse_line için kaynak koduna bakabilirsiniz.

+1

"Bunu nasıl yaparım?" Perl hakkında hiç sorduğum soru hızla "Tam olarak ne istediğinizi yapan bu modülü kullanın" tarafından hızlı bir şekilde cevaplandı. – jergason

+0

Rakamlar tam ihtiyacım olan şeyi yapmak için bir paket var. Ne aradığımdan emin değildim. Sen bir rock yıldızısın, teşekkürler! – Kivin

+5

@Jergason, harika bir insanı, ne zaman ihtiyaç duyduklarını tam olarak öğrenmediklerinde ve kendileri yazmaları gerektiğinde, sonuçtan sonra CPAN'ı suçluyorlar. :) – hobbs

2

Yani regex kullanmaya karar verdiniz mi? Şimdi iki problemin var.

Biraz çıkarım. Bir alanın boşluk içermeyen bir metinden oluştuğu ya da boşluklarla ayrılmış olduğu ve bir alıntı ile başlayıp bir alıntı ile biten (muhtemelen aradaki boşluklarla), alanların rasgele sayılarını istersiniz. Başka bir deyişle, komut satırı kabuğunun ne yaptığını yapmak istersiniz. Gerçekten bir şeyi tekrar kullanmalısın. Bu gerçekleşmediği takdirde, sizin gibi regex şey ile, bir seferde bir alan yakalamak olmalıdır: listenize grubu bir ekleme

^ *([^ ]+|'[^']*')(.*) 

, grup 2'de

A içeriğiyle döngü devam Bir regex ile tek geçiş, keyfi olarak çok sayıda alanı yakalayamazdı. Bir regex'e bölünebilir (python bunu yapacaktır, perl hakkında emin değil), ama nesneleri boşlukların dışında eşleştirdiğiniz için, bunun bir seçenek olduğundan emin değilim.

3
use strict; use warnings; 

my $text = "abcd efgh 'ijklm no pqrs' tuv 'xwyz 1234 9999' 'blah'"; 
my @out; 

my @parts = split /'/, $text; 

for (my $i = 1; $i < $#parts; $i += 2) { 
    push @out, split(/\s+/, $parts[$i - 1]), $parts[$i]; 
} 

push @out, $parts[-1]; 

use Data::Dumper; 
print Dumper \@out;