Удалить элементы с расширением точки из списка, используя регулярное выражение или сопоставление строк

Я новичок в Tcl. У меня есть список, как это:

set list1 {
    dir1
    fil.txt
    dir2
    file.xls
    arun
    baskar.tcl
    perl.pl
}

Из этого списка я хочу только такие элементы, как:

dir1
dir2
Арун

Я попробовал regexp а также lsearch но не повезло.

Способ 1:

set idx [lsearch $mylist "."]

set mylist [lreplace $mylist $idx $idx]

Способ 2:

set b [regsub -all -line {\.} $mylist "" lines]

3 ответа

Решение

Метод 1 будет работать, если вы сделали это правильно. lsearch по умолчанию возвращает один результат, а критерии поиска принимают шаблон глобуса. С помощью . будет искать только элемент, равный ., Тогда вам понадобится петля для lreplace:

set idx [lsearch -all $list1 "*.*"]
foreach id [lsort -decreasing $idx] {
    set list1 [lreplace $list1 $id $id]
}

Сортировка по убыванию важна, потому что индекс элементов будет меняться при удалении элементов (также обратите внимание, что вы использовали неверное имя переменной в своих фрагментах кода).


Метод 2 также будет работать, если вы используете правильное регулярное выражение:

set b [regsub -all -line {.*\..*} $list1 ""]

Но в этом случае вы, вероятно, захотите урезать результаты. .* будет соответствовать любым символам, кроме новой строки.


Я бы наверное использовал lsearch вот так, что исключает необходимость замены:

set mylist [lsearch -all -inline -not $list1 "*.*"]

Также можно отфильтровать список непринятых элементов, используя lmap (или явный цикл с использованием foreach):

lmap el $list1 {if {[string first . $el] >= 0} {continue} else {set el}}

Смотрите также связанное обсуждение по фильтрации списков, например, Использование `lmap` для фильтрации списка строк.

Команда lsearch имеет много опций, некоторые из которых могут помочь сделать эту задачу довольно простой:

lsearch -all -inline -not $list1 *.*
Другие вопросы по тегам