2016-06-30 4 views
0

Ich habe Zeilen von Daten in ein Array in Perl gelesen werden, das wie folgt aussieht:Legen Sie Anführungszeichen um Datum in der Nähe von Ende der Zeichenfolge in Perl mit regex

aaa bbb ccc ddd - 
aaa bbb ccc ddd eee - 

Ich versuche, in Anführungszeichen bestimmte Bereiche zu injizieren in jeder Zeile - der letzte und der drittletzte. Ich würde die Linien mag so aussehen, wenn ich fertig bin:

aaa bbb "ccc ddd" - 
aaa bbb ccc "ddd eee" - 

Ich habe versucht, die Linie in ein Array aufteilen und mit Hilfe der @array [-3] Notation, aber das geteilte entledigt Alle Leerzeichen werden als Trennzeichen verwendet. Ich glaube, ich brauche eine Rückreferenzierung mit einem Substitutions- etwas ähnliches zu verwenden:

s/(\s+[^\s]*\s+)$/\"$+\"/ 

Außer, dass ich nicht herausfinden können, wie das Spiel zu machen, die spezifischen Felder, die ich brauche und überspringen die letzten. Momentan wird das letzte Anführungszeichen nach dem Zeilenumbruch eingefügt.

Antwort

1

Beschreibung

\w+\s+\w+(?=\s-) 

Ersetzen durch:"$0"

Regular expression visualization

** Um das Bild besser zu sehen, einfach mit der rechten klicken Sie auf das Bild und wählen Sie Ansicht in einem neuen Fenster

Beispiel

Live Demo

https://regex101.com/r/dO1oU9/1

Beispieltext

aaa bbb ccc ddd - 
aaa bbb ccc ddd eee - 

Nach Ersatz

aaa bbb "ccc ddd" - 
aaa bbb ccc "ddd eee" - 

Erklärung

NODE      EXPLANATION 
---------------------------------------------------------------------- 
    \w+      word characters (a-z, A-Z, 0-9, _) (1 or 
          more times (matching the most amount 
          possible)) 
---------------------------------------------------------------------- 
    \s+      whitespace (\n, \r, \t, \f, and " ") (1 or 
          more times (matching the most amount 
          possible)) 
---------------------------------------------------------------------- 
    \w+      word characters (a-z, A-Z, 0-9, _) (1 or 
          more times (matching the most amount 
          possible)) 
---------------------------------------------------------------------- 
    (?=      look ahead to see if there is: 
---------------------------------------------------------------------- 
    \s      whitespace (\n, \r, \t, \f, and " ") 
---------------------------------------------------------------------- 
    -      '-' 
---------------------------------------------------------------------- 
)      end of look-ahead 
---------------------------------------------------------------------- 
+0

Vielen Dank für die Antwort. Ich bin wirklich noch ziemlich neu in Regex - ich dachte, ich müsste Rückreferenzen verwenden, um etwas zu ersetzen. Wenn ich in Perl ein Gleiches mache wie '$ var = ~ s/\ w + \ s + \ w + (?= \ s -)/$ 0/', wird es standardmäßig mit der ganzen Zeichenfolge übereinstimmen? – Basil

+0

Und noch eine Frage - wenn ich der letzten Spalte erlauben wollte, dass sie irgendwas ist, nicht nur ein Bindestrich, würde sie in \ w + $ work ändern, so: '$ var = ~ s/\ w + \ s + \ w + (? = \ s + \ w + $)/$ 0/'? – Basil

+0

Erste Frage: Der Lookahead '(? = \ S-)' schaut einfach voraus, um zu sehen, ob die nächsten Zeichen ein Leerzeichen gefolgt von einem Bindestrich sind. Der Blick nach vorne sieht einfach aus, ob das die nächsten Zeichen sind, aber sie werden nicht in das Capture aufgenommen. Auch die Suchfunktion in Perl ist nur 's /...../' in Ihrer Frage würde das abschließende '$ 0 /' verwendet werden, wenn Sie eine Ersetzung ausführen. aber das Ersetzen der gesamten gefundenen Zeichenfolge durch $ 0 würde keine Änderungen ergeben. –

1

hier Nachgewiesene: https://regex101.com/r/zD3cP9/2

Mit dem Muster

((?:\w+\s*){2})(\s+-) 

ausgeführt auf

aaa bbb ccc ddd - 
aaa bbb ccc ddd eee - 

wäre

aaa bbb "ccc ddd" - 
aaa bbb ccc "ddd eee" - 

Dieser wiederholt das erste Teilmuster zweimal, da es nach einem Strich sucht, um es zu vervollständigen. Nützlich, weil es leicht zu pflegen ist.

+0

Danke! Also, wenn ich das verstehe, ist der erste Teil '(?: \ W + \ s *) {2}' ein Lookahead, der nach einem Wort und dann 0 oder mehr Leerzeichen zweimal sucht, und der zweite Teil entspricht Whitespace dann einem Strich? – Basil

+1

Sie müssen mit dieser Art von Ausdruck vorsichtig sein, weil das '\ s *' keine oder mehr Leerzeichen erlaubt ... und das zweimal zu tun ist wie zu sagen, finde eine Zeichenkette mit 1 oder mehr Zeichen, gefolgt von 0 oder mehr Leerzeichen, gefolgt von 1 oder mehr Zeichen gefolgt von 0 oder mehr Leerzeichen. Mit anderen Worten, ein zweistelliges Wort wie "ab" könnte mit diesem Ausdruck übereinstimmen, da es null Leerzeichen zwischen den Buchstaben "a" und "b" und null Leerzeichen nach dem Buchstaben "b" enthält. Dies kann zu einigen unerwarteten Ergebnissen führen. –

Verwandte Themen