Регулярное выражение для разбора пар имя-значение - PullRequest
19 голосов
/ 03 октября 2008

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

AssemblyName=foo.dll,ClassName="SomeClass",Parameters="Some,Parameters"

Ответы [ 3 ]

35 голосов
/ 03 октября 2008
  • Нет выхода:

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

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

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

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

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

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

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

2 голосов
/ 03 октября 2008

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

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

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

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

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

#!/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 доллара не определены - точно.

0 голосов
/ 16 октября 2008

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

qr/
  (?<key>
    (?:
      [^=,\\]
    |
      (?&escape)
    )++ # Prevent null keys
  )

  \s*+
  =
  \s*+

  (?<value>
    (?&quoted)
  |
    (?:
      [^=,\s\\]
    |
      (?&escape)
    )++ # Prevent null value ( use quotes for that )
  )

  (?(DEFINE)
    (?<escape>\\.)
    (?<quoted>
      "
        (?:
          (?&escaped)
        |
          [^"\\]
        )*+
      "
    )
  )
/x

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

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

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