it-swarm.com.ru

Регулярное выражение для разбора пар имя-значение

Может ли кто-нибудь предоставить регулярное выражение для разбора пар имя/значение из строки? Пары разделены запятыми, а значение может быть заключено в кавычки. Например:

AssemblyName=foo.dll,ClassName="SomeClass",Parameters="Some,Parameters"
19
Chris Karcher
  • Нет выхода:

    /([^=,]*)=("[^"]*"|[^,"]*)/
    
  • двойная кавычка для ключа и значения:

    /((?:"[^"]*"|[^=,])*)=((?:"[^"]*"|[^=,])*)/
    
    key=value,"key with "" in it"="value with "" in it",key=value" "with" "spaces
    
  • обратная косая черта escape:

    /([^=,]*)=("(?:\\.|[^"\\]+)*"|[^,"]*)/
    
    key=value,key="value",key="val\"ue"
    
  • Полный обратный слэш:

    /((?:\\.|[^=,]+)*)=("(?:\\.|[^"\\]+)*"|(?:\\.|[^,"\\]+)*)/
    
    key=value,key="value",key="val\"ue",ke\,y=val\,ue
    

Edit: Добавлены экранирующие альтернативы.

Edit2: Добавлена ​​еще одна альтернатива.

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

35
Markus Jarderot

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

Как написано, шаблон работает с большинством расширенных систем регулярных выражений. Для исправления ошибок, возможно, потребуется спуск, скажем, в Perl. Эта версия использует двойные кавычки для выхода - следовательно, a = "a" "b" генерирует значение поля 'a "" b' (которое не является идеальным, но впоследствии может быть исправлено достаточно легко):

/\s*([^=,\s]+)\s*=\s*(?:"((?:[^"]|"")*)"|([^,"]*))\s*,?/

Кроме того, вам придется использовать $ 2 или $ 3 для сбора значения, тогда как с ответом MizardX вы просто используете $ 2. Так что это не так просто и приятно, но охватывает несколько случаев Edge. Если более простой ответ является адекватным, используйте его.

Тестовый скрипт:

#!/bin/Perl -w

use strict;
my $qr = qr/\s*([^=,\s]+)\s*=\s*(?:"((?:[^"]|"")*)"|([^,"]*))\s*,?/;

while (<>)
{
    while (m/$qr/)
    {
        print "1= $1, 2 = $2, 3 = $3\n";
        $_ =~ s/$qr//;
    }
}

Это свидетельствует о том, что $ 2 или $ 3 не определены - точно.

2
Jonathan Leffler

Вот как бы я это сделал, если бы вы могли использовать Perl 5.10.

 qr /
 (? <ключ> 
 (?: 
 [^ =, \\] 
 | 
 (? & escape) 
) ++ # Запретить нулевые ключи 
) 
 
\s * + 
 = 
\s * + 
 
 (? <value> 
 (? & quote) 
 | 
 (?: 
 [^ =,\s \\ ] 
 | 
 (? & escape) 
) ++ # Запретить нулевое значение (используйте для этого кавычки) 
) 
 
 (? (DEFINE) 
 (? <Escape> \\.) 
 (? <Quote> 
 "
 (?: 
 (? и сбежал) 
 | 
 [^ "\\] 
) * + 
" 
) 
) 
 /Икс

Элементы будут доступны через %+.

perlretut очень помогли в создании этого ответа.

0
Brad Gilbert