2016-05-31 53 views
2

每個查詢的第一個實例我有一個包含一些值的列表變量:正則表達式循環找到TCL

lappend list {query1} 
      {query2} 
      {query3} 

而且一些數據文件1相匹配的值,並將它們的部分上面

query1 first data 
query1 different data 
query1 different data 
query2 another data 
query2 random data 
query3 data something 
query3 last data 

如何創建一個正則表達式循環,僅捕獲每個查詢的第一個實例並將其打印出來?在這種情況下,輸出將是:

query1 first data 
query2 another data 
query3 data something 

試圖代碼產生輸出

set readFile1 [open file1.txt r] 
while { [gets $readFile1 data] > -1 } { 
for { set n 0 } { $n < [llength $list] } { incr n } { 
if { [regexp "[lindex $list $n]" $data] } { 
puts $data 
} 
} 
} 
close $readFile1 

我在閱讀該文件中的數據使用for循環試過,但它似乎捕捉所有值,即使沒有使用-all選項。

回答

2

如果文本文件的大小較小,可以使用read命令將文件作爲整體讀入到變量中。爲內容應用regexp,我們可以提取所需的數據。

set list {query1 query2 query3} 
set fp [open file1.txt r] 
set data [read $fp] 
close $fp 
foreach elem $list { 
    # '-line' flag will enable the line sensitive matching 
    if {[regexp -line "$elem.+" $data line]} { 
     puts $line 
    } 
} 

如果假設文件太大,無法保存或者如果您考慮運行時內存使用情況,請繼續逐行讀取內容。在那裏,我們需要控制已經匹配的內容,您可以使用該內容來維護數組是否匹配任何查詢的第一個匹配項。

set list {query1 query2 query3} 
set fp [open file1.txt r] 
array set first_occurence {} 
while {[gets $fp line]!=-1} { 
    foreach elem $list { 
     if {[info exists first_occurence($elem)]} { 
      continue 
     } 
     if {[regexp $elem $line]} { 
      set first_occurence($elem) 1 
      puts $line 
     } 
    } 
} 
close $fp 

參考:regexp

+1

在使用in運算符的行中搜索查詢字符串是lik如果例如該行不是一個正確的列表,就會引起問題。另外,如果查詢字符串是正則表達式,則很可能會失敗。 –

+0

@PeterLewerin:明白了。解決了同樣的問題。 – Dinesh

1

試試這個,

set fd [open "query_file.txt" r] 
set data [read $fd] 
set uniq_list "" 
foreach l [split $data "\n"] { 
    lappend uniq_list [lindex $l 0] 
} 

set uniq_list [lsort -unique $uniq_list] 

foreach l $uniq_list { 
    if {[string equal $l ""]} { 
     continue 
    } 
    foreach line [split $data "\n"] { 
     if {[regexp $l $line]} { 
      puts "$line" 
      break 
     } 
    } 
} 

close $fd 

參考文獻:filelistregexp

+0

請注意,您的解決方案不一定匹配問題,例如,如果有行不包含查詢字符串,如果查詢字符串可以有空格,如果查詢字符串可能發生在其他地方而不是在行,如果第一行與給定的查詢字符串不是第一個按排序順序,等等。 –

+0

對不起,我完全誤解了這個問題,我沒有看到這行已經查詢部分是另一個列表lappend list {query1} {query2 } {query3}'。我認爲我們也需要從文本文件中獲取查詢值 –

2
package require fileutil 

set queries {query1 query2 query3} 
set result {} 
::fileutil::foreachLine line file1.txt { 
    foreach query $queries { 
     if {![dict exists $result $query]} { 
      if {[regexp $query $line]} { 
       dict set result $query $line 
       puts $line 
      } 
     } 
    } 
} 

這裏的竅門是存儲的調查結果在字典中。如果字典中已經有與查詢相對應的值,我們不會再次搜索它。這也有一個好處,即找到的行在搜索後可用於腳本,而不僅僅是打印出來。 regexp搜索在該行的任何位置查找查詢字符串:如果它只應位於行的開頭,則改爲使用regexp ^$query $line

文檔:dictfileutil包,foreachifpackageputsregexpset

1

不使用正則表達式都:我認爲你的 「查詢」 S不包含空格

set list [list query1 query2 query3] 
array set seen {} 
set fh [open file1] 
while {[gets $fh line] != -1} { 
    set query [lindex [split $line] 0] 
    if {$query in $list && $query ni [array names seen]} { 
     set seen($query) 1 
     puts $line 
    } 
} 
query1 first data 
query2 another data 
query3 data something