2016-05-17 12 views
2

I somefile.txt haben, enthält Zeilen wie:Muster in Tcl passend

{ abc1 } 1 
{ cde1 } 101 
{ fgh1 } 1 
{ ijk1 } 2 

sein eine riesige Datei, ich nur 1. und 3. Zeile und sie finden wollten zählen.

Ich habe versucht mit regexp und lsearch (Umwandlung in die Liste) von {\s\}\s1\n}, aber es funktioniert nicht. Was soll ich machen...?

Ich habe auch {\s\}\s1} versucht, aber es druckt alle 4 Zeilen.

+0

Sie Frage ist sehr unklar: Welche Ausgabe möchten Sie sehen? –

+0

Also, wollen Sie 1 + 1 zusammenfassen? –

+0

OK, ich wollte nur die Zeile sehen, die mit 1 (nur 1, nicht einmal 111,101 oder 100) außerhalb der geschweiften Klammern endet. Es gibt Millionen von Zeilen, ich habe hier nur vier gezeigt, innerhalb der Klammer sind Zeichen wie "", [], /, zB {a/b "[c]} 1 auch da. – ShivankG

Antwort

0

Lösung 1: Wenn Sie nicht wollen, zu ihrer Verwendung regexp und Ihre Eingaben Linie haben format wie {string} number

set fd [open "somefile.txt" r] 
while {[gets $fd line] >= 0} { 
    if {[lindex $line 1] == 1} { 
     puts [lindex $line 1] ;# Prints only 1 
     puts $line   ;# Prints Whole Line which has 1 at end 
    } 
} 

Lösung: gehen Wenn Sie regexp verwenden möchten, dann für group-capturing die (.*)

set fd [open "somefile.txt" r] 
while {[gets $fd line] >= 0} { 
    if {[regexp "\{.*\} (.*)" $line match match1]} { 
     if {$match1 == 1} { 
      puts $line 
     } 
    } 
} 

Lösung 3: Basierend auf @ Peter Vorschlag auf regexp

set fd [open "somefile.txt" r] 
while {[gets $fd line] >= 0} { 
    if {[regexp {\d+$} $line match]} { 
     if {$match == 1} { 
      puts $match ;# Prints only 1 
      puts $line ;# Prints whole line which has 1 at end 
     } 
    } 
} 
+0

Besser regexp:' regexp {\ d + $} $ Zeilenabgleich', th en vergleiche '$ match' mit 1. –

+0

@ Axt_8041: Genius – ShivankG

+0

@PeterLewerin zu meinem Verständnis, Ihre gegebene regexp findet alle Ziffern am Ende. Ich bin richtig? –

0

Sie scheinen die Ziffern am Ende der ersten und dritten Zeile zu erfassen.

Hier ist ein Weg, das zu erreichen:

set s {{ abc1 } 1 
{ cde1 } 101 
{ fgh1 } 1 
{ ijk1 } 2} 
set re {^{[^{}]*}\s*(\d+)\s+{[^{}]*}\s*\d+\s+{[^{}]*}\s*(\d+)} 
regexp $re $s m g1 g2 
set res [expr $g1 + $g2] 
puts $res 

Siehe IDEONE demo

Das Muster passt:

  • ^ - Beginn einer
  • {[^{}]*}
  • string - ein {...} - wie Schnur ohne Klammern innen
  • \s* - 0+ Whitespaces
  • (\d+) - Gruppe 1 (g1) Erfassung 1+ Ziffern
  • \s+ - 1+ Whitespaces (mit [\r\n]+ ersetzt werden, wenn es kein nachlauf sein/Leerzeichen führen vor und nach)
  • {[^{}]*}\s*\d+\s+{[^{}]*}\s*(\d+) - siehe oben, nur (\d+) erstellt eine zweite Variable, g2.

Siehe regex demo

0

ein Problem wie dieses wird um einen Auftrag oder Größe leichter zu lösen, wenn Sie reguläre Ausdrücke nicht verwenden.

package require fileutil 

::fileutil::foreachLine line somefile.txt { 
    if {[lindex $line end] == 1} { 
     puts $line 
    } 
} 

Diese Lösung sieht in jeder Zeile in der Datei und prüft, ob das letzte Element gleich 1 ist, wenn dem so ist, die Zeile gedruckt wird.

Sie auch sie zählen konnte/sie summieren:

set count 0 
set sum 0 
::fileutil::foreachLine line somefile.txt { 
    if {[lindex $line end] == 1} { 
     puts $line 
     incr count 
     incr sum [lindex $line end] ;# yeah, I know, always 1 
    } 
} 
puts "Number of lines: $count" 
puts "Sum of items: $sum" 

Wenn fileutil ist in Ihrer Tcl-Installation nicht zur Verfügung und Sie können es nicht oder wollen nicht installieren, der Minus- verwenden können Ebene Kern äquivalent:

set f [open somefile.txt] 
while {[gets $f line] >= 0} { 
    if {[lindex $line end] == 1} { 
     puts $line 
    } 
} 
close $f 

Wenn Sie unbedingt einen regulären Ausdruck, in diesem Fall verwenden, müssen Sie dies tun könnte:

::fileutil::foreachLine line somefile.txt { 
    if {[regexp {\m1$} $line]} { 
     puts $line 
    } 
} 

Dieser reguläre Ausdruck findet Zeilen, die mit der Ziffer 1 in einem Wort enden (d. H. davor gibt es keine Ziffern oder Wortzeichen).

Dokumentation: close, fileutil Paket, gets, if, lindex, open, package, puts, Syntax of Tcl regular expressions, regexp, while

+0

ja ich wollte diese Zeilen drucken, die endet am Ende mit 1 (nur 1, nicht einmal 111,101 oder 100), ich kann keine Werte in Klammern verwenden, denn es gibt Millionen von Zeilen und alle haben unterschiedliche Namen in Klammern, aber es gibt einige Zeilen, die mit 1 enden, wollte ich Drucken Sie nur diese Zeilen. – ShivankG

+0

@ShivankG: aktualisiert die Lösung. –

+0

Ich denke, dass ur-Code funktioniert, aber ich bin nicht in der Lage, fileutil zu verwenden, verwende ich tcl auf Linux-Maschine.Thank Sie – ShivankG