2013-07-26 2 views
0

Я новый ученик для tcl. У меня есть некоторые проблемы, как показано ниже при использовании regsub. Рассмотрим следующий сценарий:нужна помощь в использовании команды tcl для regsub

set test1 [list prefix_abc_3 abc_1 abc_2 AAA_0] 

set test2 abc 

regsub -all ${test2}_[1-9] $test1 [list] test1 

Я ожидал $test1 output is [prefix_abc_3 AAA_0]

Однако regsub также удалить частичную найденную строку, которая prefix_abc_3. Кто-нибудь здесь имеет представление о том, как записывать точные слова только в списке?

Я попытался найти решение через сеть, но не смог получить подсказки/подсказки. Цените, если кто-то здесь может мне помочь.

+0

Используйте обратную косую черту перед [1-9] (при условии \\ [1-9 \\]), потому что иначе она будет выглядеть как 1-9 в качестве команды для выполнения. – Roalt

ответ

1

\m and \M в регулярных выражениях соответствуют началу и концу слова соответственно. Но у вас нет строки слов в test1, но список элементов, а иногда есть разница, поэтому не смешивайте их. regsub обрабатывает только строки в то время как lsearch работает со списками:

set test1 [list prefix_abc_3 abc_1 abc_2 AAA_0] 
set test2 abc 
set test1 [lsearch -all -inline -not -regexp $test1 "^${test2}_\[1-9\]\$"] 

Если шаблон просто, вы можете использовать -glob вариант (по умолчанию) вместо -regexp и, возможно, сэкономить время процессора.

+0

Вы решили мое сомнение. спасибо за просвещенную меня, Потцзеби. Ценит много :) – user2622414

+0

В 8.6: 'lmap element $ test1 {regsub $ test2 $ element" "}' –

+0

@ user2622414 Если вы согласны с ответом, щелкните отмеченную галочку в левом верхнем углу. – potrzebie

0

точно Вы выполнили?

Когда я набираю команды выше в tclsh, он выводит сообщение об ошибке -

% set test1 [list prefix_abc_3 abc_1 abc_2 AAA_0] 
prefix_abc_3 abc_1 abc_2 AAA_0 
% set test2 abc 
abc 
% regsub -all ${test2}_[1-9] [list] test1 
invalid command name "1-9" 

Я не уверен, что вы пытаетесь сделать. Вы начинаете с inisitalising test1 как . Затем вы обрабатываете его как строку , передавая ее в regsub. Это совершенно законная вещь, но может указывать на то, что вы что-то сбиты с толку. Вы пытаетесь проверить свою замену, применяя ее четыре раза, к каждому из prefix_abc_3, abc_1, abc_2 и AAA_0? Можно конечно делать это способ, которым Вы, но более естественным способом станет делать

foreach test $test1 { 
    regsub $pattern $test [list] testResult 
    puts stdout $testResult 
} 

Опять, чего вы пытаетесь достичь с помощью подстановки? Похоже, что вы пытаетесь заменить строку abc пустой строкой, т. Е. Полностью удалить ее. Передача [list] в виде нулевой строки вполне допустима, но снова может указать путаницу между списками и строками.

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

regsub -all " ${test2}_\[-9\]" $test1 " " test1 

, но я подозреваю, что это составленный пример, и вы действительно пытаетесь сделать что-то немного другое.

Редактировать

Чтобы получить список, содержащий только те записи списка, которые не точно соответствуют шаблону, я предлагаю

proc removeExactMatches {input} { 
    set result [list];  # Initialise the result list 
    foreach inputElement $input { 
     if {![regexp {^abc_[0-9]$} $inputElement]} { 
      lappend result $inputElement 
     } 
    } 
    return $result 
} 

set test1 [removeExactMatches [list prefix_abc_3 abc_1 abc_2 AAA_0]] 

Примечания:

я) Я не» t использовать regsub вообще.

ii) Хотя безопасно и законно переключаться между списками и строками, все это требует времени, и это заслоняет то, что я пытаюсь сделать, поэтому я избегаю его, когда это возможно. Кажется, у вас есть список строк, и вы хотите удалить некоторые из них, так что это то, что я использую в своем предлагаемом решении. Команды регулярного выражения в дескрипторе Tcl строки, поэтому я передаю им строки.

iii) Чтобы убедиться, что элементы списка соответствуют точно, я привязываю шаблон к началу и концу строки, которую я сопоставляю, используя ^ и $.

iv) Чтобы предотвратить интерпретацию интерпретатора [1-9] в шаблоне регулярных выражений и попытку выполнить (несуществующую) команду 1-9, я заключу целую строку шаблона в фигурные скобки.

v) Для большей общности, я мог бы передать картину в прок, а также список ввода (строк), в этом случае, я бы

proc removeExactMatches {inputPattern input} { 
    . 
    . 
    . 
    set pattern "^" 
    append pattern $inputPattern 
    append pattern "\$" 
    . 
    . 
    . 
     if {![regub $pattern $inputElement]} { 
     . 
     . 
     . 
} 

set test1 [removeExactMatches {abc_[1-9]} {prefix_abc_3 abc_1 abc_2 AAA_0}] 

, чтобы минимизировать число символов, которые должны были быть экранированы. (На самом деле я, вероятно, не использовал бы кавычки для стартовых и конечных якорей в пределах proc - они на самом деле не нужны, и я ленивый машинист!)

Посмотрев на свой первоначальный вопрос, кажется, что вы может хотеть варьировать только часть шаблона abc, и в этом случае вы можете просто передать это на ваш proc и добавить _[0-9], а также якоря внутри него - не забудьте выйти из квадратных скобок или использовать фигурные скобки если вы спуститесь по этому маршруту.

+0

Hi Nurdglaw, Спасибо, что заглянули в мои сомнения. на самом деле вы пропустили $ test в команде regsub, что причина, по которой она указала ошибку. Ваша пробная команда% regsub -all $ {test2} _ [1-9] <пропущенный $ test1 здесь> [list] test1 – user2622414

+0

Ваш пример foreach является одним из способов замены, но они могут не выдавать вывод, который я ищу, потому что они заменит любой шаблон, соответствующий abc_ , на null. и то, что я пытаюсь сделать, это заменить всю строку соответствия только abc_ . ниже показывает, что я ожидаю получить от результата перед: test1 список [prefix_abc_1 abc_1 abc_0 abc_6 Защиту] с llength = 5 после: test1 список с [prefix_abc_1 Защиту] с llength = 2 надежды это позволит вам понять мой вопрос. спасибо :) – user2622414

Смежные вопросы