Разбор строки TCL с escape-символами - PullRequest
0 голосов
/ 24 октября 2019

Замечание и вопрос.

Дан текстовый файл со строками, которые содержат escape-символы. Т.е. обратная косая черта. Разбор этих строк и разделение контента с использованием lindex и lassign уничтожают escape-символы. Это полу вопрос. Я подозреваю, что в TCL назначение включает в себя разбор целевого объекта и, следовательно, обработку escape-символов. Интересно, есть ли способ обойти это.

Мое наблюдение состоит в том, что только регулярное выражение могло разделить строку без обработки.

Я уверен, что текстовый редактор форума испортит мой тестовый файл,(Ну что ж, это не так)

% cat lines.txt
1 a/b/c/d[7]
2 a/b\/c\/d\[7\]
3 a\/b/c/d[7]

set fp [ open lines.txt ]
set rpt [ read $fp ]
close $fp

foreach line [ split $rpt \n ] {
    set val [ lindex $line 0 ]
    set str [ lindex $line 1 ]
    puts "val= $val : str= $str"
}

val= 1 : str= a/b/c/d[7]
val= 2 : str= a/b/c/d[7]
val= 3 : str= a/b/c/d[7]
val=  : str=

foreach line [ split $rpt \n ] {
    lassign $line val str
    puts "val= $val : str= $str"
}

val= 1 : str= a/b/c/d[7]
val= 2 : str= a/b/c/d[7]
val= 3 : str= a/b/c/d[7]
val=  : str=

foreach line [ split $rpt \n ] {
    regexp {(\S+)\s+(\S+)} $line dmy val str
    puts "val= $val : str= $str"
}

val= 1 : str= a/b/c/d[7]
val= 2 : str= a/b\/c\/d\[7\]
val= 3 : str= a\/b/c/d[7]
val= 3 : str= a\/b/c/d[7]

Ответы [ 2 ]

2 голосов
/ 24 октября 2019

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

foreach line [ split $rpt \n ] {
    lassign [split $line " "] val str
    puts "val= $val : str= $str"
}

Если это не сработает, потому чтомежду полями может быть более одного символа пробела, вы можете использовать splitx, который разделяется на регулярное выражение вместо простого символа:

package require textutil::split
foreach line [ split $rpt \n ] {
    lassign [textutil::split::splitx $line] val str
    puts "val= $val : str= $str"
}
0 голосов
/ 27 октября 2019

Существуют три основные команды для разбора произвольной строки в список:

  1. regexp -inline (часто с -all): это часто мой любимый в наши днипоскольку я могу просто описать правило RE для того, что такое слово, и сделать так, чтобы оно сделало всю работу за меня.
  2. split, если вы хотите, чтобы оно выполнялось: иногда можно предварительно подготовить строку (используя необычные символы Юникода), чтобы сделать эту работу лучше, но мне самому это не нравится.
  3. scan без переменных: каждый сам это забудетвключены ...

Вы также можете делать что-то по частям (или использовать библиотечную функцию, которая обрабатывает детали, например, textutil::splitx).


Операции со спискомСами по себе не работают с произвольными строками, а только с теми строками, которые соответствуют правилам формата списка. Обратная косая черта в этих правилах особенная (как и в вашем скрипте). Так же, как и { фигурные скобки }. Обычная рекомендация состоит в том, чтобы не обрабатывать произвольные внешние данные как список Tcl, и потому, что они обычно работают с тестовыми данными и слишком часто идут неправильно в работе (но не сразу). Предварительная очистка данных экономит много царапин на голове.

...