2016-05-31 2 views
2

У меня есть список переменный, содержащие несколько значений:регулярное_выражение цикла, чтобы найти первый экземпляр каждого запроса TCL

lappend list {query1} 
      {query2} 
      {query3} 

И некоторые данные в file1 с их частями, соответствующих значения выше

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

Как создать цикл regexp, который ловит только первый экземпляр, найденный для каждого запроса, и распечатывает их? В этом случае результат будет:

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 

Я попытался с помощью цикла при чтении данных из файла, но это, кажется, поймать все даже если опция -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 is 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 

Ссылки: file, list, regexp

+0

Обратите внимание, что ваше решение не обязательно соответствует этой проблеме, например, если есть строки, которые не содержат строку запроса, если строка запроса может иметь пробелы, если строка запроса может возникать где-то еще, чем в начале line, если первая строка с заданной строкой запроса не является первой в порядке сортировки и т. д. –

+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.

Документация: dict, fileutil пакет, foreach, if, package, puts, regexp, set

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 
Смежные вопросы