2010-03-17 9 views
5

ich eine Lösung Aufteilen einer Zeichenfolge suchen, die Text in folgendem Format enthält:Wie kann ich eine Zeichenfolge durch Whitespace aufteilen, es sei denn, sie befindet sich in einer einzelnen Zeichenfolge in Anführungszeichen?

"abcd efgh 'ijklm no pqrs' tuv" 

, welches die folgenden Ergebnisse liefern:

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

Mit anderen Worten teilt sie Leerzeichen durch, es sei denn innerhalb einer einzelnen Zeichenfolge in Anführungszeichen. Ich denke, es könnte mit .NET Regexps mit "Lookaround" -Operatoren, insbesondere Balancing-Operatoren getan werden. Ich bin mir nicht sicher über Perl.

Antwort

15

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

Ausgang:

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

Sie auf den Quellcode für Text::ParseWords::parse_line aussehen kann das Muster verwendet, um zu sehen.

+1

Ich liebe, wie "wie mache ich das?" Frage, die ich jemals über Perl hatte, wurde schnell beantwortet von "Verwenden Sie dieses Modul, das genau das tut, was Sie wollen." – jergason

+0

Zahlen gibt es ein Paket, genau das zu tun, was ich brauche. Ich war mir nicht sicher, wonach ich suchte. Du bist ein Rockstar, danke! – Kivin

+5

@Jergason es den wundervollen Leuten vorwerfen, die, wenn sie * nicht genau das finden, was sie brauchen, und es selbst schreiben müssen, CPAN das Ergebnis danach. :) – hobbs

2

Sie haben sich also für einen Regex entschieden? Jetzt hast du zwei Probleme.

Erlauben Sie mir, ein wenig abzuleiten. Sie möchten eine beliebige Anzahl von Feldern, in denen ein Feld aus Text besteht, ohne ein Leerzeichen zu enthalten, oder es ist durch Leerzeichen getrennt und beginnt mit einem Zitat und endet mit einem Zitat (möglicherweise mit Leerzeichen dazwischen).

Mit anderen Worten, Sie möchten tun, was eine Befehlszeilen-Shell tut. Sie sollten wirklich nur etwas wiederverwenden. Gelingt das nicht, sollten Sie ein Feld zu einem Zeitpunkt, zu erfassen, mit einem regex so etwas wie:

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

Wo Sie Gruppe ein, um Ihre Liste anhängen, und weiterhin die Schleife mit dem Inhalt der Gruppe 2.

A Ein einzelner Durchlauf durch eine Regex wäre nicht in der Lage, eine beliebig große Anzahl von Feldern zu erfassen. Sie könnten in der Lage sein, auf einer Regex zu teilen (Python wird dies tun, nicht sicher über Perl), aber da Sie die Sachen außerhalb der Räume zusammenpassen, bin ich mir nicht sicher, ob das eine Option ist.

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; 
Verwandte Themen