Обрабатывать запятые в кавычках в Tcl - PullRequest
1 голос
/ 10 января 2011

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

set line {12,"34","56"}
set fresult [regsub -all {(\")([^\"]+)(\",)|([^,\"]+),} $line {{\2\4} } fields]
puts $fields
{12} {34} "56"

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

Однако, когда в кавычке есть запятая, она не работает:

set line {12,"34","56,78"}
set fresult [regsub -all {(\")([^\"]+)(\",)|([^,\"]+),} $line {{\2\4} } fields]
puts $fields
{12} {34} "{56} 78"

Я бы ожидал: {12} {34} {56,78}

Что-то не так с моим регулярным выражением или что-то происходит в tcl-ish?

Ответы [ 4 ]

5 голосов
/ 10 января 2011

Одна из опций, которая приходит на ум, - это использование функции CSV в TclLib. (Нет причин изобретать велосипед, если нет необходимости ...)

http://tcllib.sourceforge.net/doc/csv.html

Выписка из документа

:: csv :: split? альтернативный? линия {sepChar,} {delChar "} преобразует строка в формате CSV в список значения, содержащиеся в строке. символ, используемый для разделения значений друг от друга могут быть определены звонящий, через sepChar, но это необязательный. По умолчанию это ",". символ цитирования может быть определен звонящий, но это необязательно. по умолчанию '' '. Если опция -alternate spcified немного другой синтаксис используется для анализа вход. Этот синтаксис объясняется ниже, в разделе ФОРМАТ.

2 голосов
/ 10 января 2011

Проблема, похоже, заключается в лишней запятой: вы принимаете строки в кавычках, только если они имеют запятую после них, и делаете то же самое для токенов без кавычек. Это работает:

set fresult [regsub -all {(\")([^\"]+)(\")|([^,\"]+)} $line {{\2\4} } fields]
                                        ^(no commas)^

Рабочий пример: http://ideone.com/O2hss

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

Бонус: это также будет обрабатывать экранированные кавычки, используя \" (если вам нужно, вы можете легко адаптироваться, используя "" вместо \\.).:

set fresult [regsub -all {"((?:[^"\\]|\\.)+)"|([^,"]+)} $line {{\1\2} } fields]

Пример: http://ideone.com/ztkBh

0 голосов
/ 19 января 2011

Используйте следующий regsub

% set line {12,"34","56,78"}

% regsub -all {(,")|(",)|"} $line " " line

% set line

12 34  56,78  <<< Result

Здесь все вхождения ," или ", или " (по порядку) заменены пробелом

0 голосов
/ 10 января 2011

Как вы сказали @Kobi, если вы разрешаете пустые поля, вы должны разрешить пустые строки "" {((\")([^\"]*)(\")|([^,\"]*))(,|$)}, где поля интереса сместились на 3 и 5

Расширен: { ( (\")([^\"]*)(\") | ([^,\"]*) ) (,|$) } Признаюсь, я не знаю, позволяет ли tcl (? :) группировать без захвата.

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