Нужно регулярное выражение для сопоставления пар имя / значение в разных форматах - PullRequest
0 голосов
/ 02 февраля 2011

Я загружаю файлы конфигурации ASP / VBScript через PHP Curl, чтобы выполнить некоторую обработку файла и хочу вернуть некоторые значения.

Строки выглядят так:

config1 = ""  
config2 = "VALUE:1:0:9" 'strange value comment 
otherconfig = False 
yetanotherconfig = False 'some comment

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

Я хочу вернуть фактическое значение (False, VALUE: 1:0: 9 и т. Д.) В ОДНОЙ группе соответствия независимо от формата, в котором находится строка.

Вот шаблон, который я передаю в preg_match:

$pattern = '/\s*'.$configname.'\s*\=\s*(\".*?\"|.*?\r)/'

$ confignameэто имя конкретной конфигурации, которую я ищу, поэтому я передаю ее с помощью переменной.

Я все еще получаю скобки, включенные обратно со значением (вместо самого значения), и я также получаю комментарии, возвращаемые со значением.

Любая помощь приветствуется!

Ответы [ 3 ]

1 голос
/ 02 февраля 2011

Возвращение соответствующего значения в ОДНОЙ группе соответствия, если это затруднительно из-за альтернативы двойных кавычек Обратные ссылки могут помочь:

$pattern = '/\s*'.$configname.'\s*=\s*("?)(?<value>.*?)\1\s*[\'$]/'

должен сделать свое дело. Тогда используйте $result['value'].

Объяснено на английском это:

  • Я пропускаю идентификатор пробела Пробелы = Пробелы (легко)
  • может соответствовать ", указанному как \ 1 (первая скобка захвата)
  • соответствует любому символу, на который жадно не ссылаются как value
  • соответствует \ 1 (поэтому ", если он был раньше, или ничего, если нет)
  • может соответствовать некоторым пробелам
  • должен соответствовать начальный комментарий ' или конец строки

Без обратных ссылок:

$pattern = '/\s*'.$configname.'\s*=\s*(?:"(.*?)"|(.*?)\s*[\'$])/'

Более эффективно, но значение в $result[1] или $result[2].

Поймите ваши ошибки:

  • Вам нужно \ только для защиты самой строковой кавычки (здесь простая кавычка) или во избежание интерпретации preg зарезервированного символа (как ., ^, $ ...)
  • Конец строки помечается как $, а не \ r или \ n
  • Вы никогда не избегали комментариев
0 голосов
/ 02 февраля 2011

Это будет работать:

$pattern = '/
    \s*
    # name
    (?P<name>.*?)
    # =
    \s*=\s*
    # value
    (?P<val>
        "(?P<quoted>([^"]|\\\\"|\\\\\\\\)*)"
        |(?P<raw>.*?)
    )
    # comment
    \s*(?P<comment>\'.*)?
$/xm';

Это будет соответствовать каждой паре ключ = значение во входной строке, а не только конкретной.

Регулярное выражение заботится о кавычках иэкранированные кавычки (\") в кавычках (например, "foo\"bar").

Используйте его с такой функцией:

function parse_config($string) {
    $pattern = '/
        \s*
        # name
        (?P<name>.*?)
        # =
        \s*=\s*
        # value
        (?P<val>
            "(?P<quoted>([^"]|\\\\"|\\\\\\\\)*)"
            |(?P<raw>.*?)
        )
        # comment
        \s*(?P<comment>\'.*)?
    $/xm';

    preg_match_all($pattern, $string, $matches, PREG_SET_ORDER);

    $config = array();
    foreach($matches as $match) {
        $name = $match['name'];
        if (!empty($match['quoted'])) {
            $value = str_replace(array('\\"','\\\\'), array('"','\\'), $match['quoted']);
        } else if (isset($match['raw'])) {
            $value = $match['raw'];
        } else {
            $value = '';
        }
        $config[$name] = $value;
    }

    return $config;
}

Пример:

$string = "a = b\n
c=\"d\\\"e\\\\fgh\" ' comment";

$config = parse_config($string);

// output:

array('a' => 'b', 'c' => 'd"e\fgh');

Другой пример:

$string = <<<EOF
config1 = ""
config2 = "VALUE:1:0:9" 'strange value comment
otherconfig = False
yetanotherconfig = False 'some comment
EOF;

print_r(parse_config($string));

// output:

Array
(
    [config1] => 
    [config2] => VALUE:1:0:9
    [otherconfig] => False
    [yetanotherconfig] => False
)
0 голосов
/ 02 февраля 2011

\ r будет соответствовать символу CR (возврат каретки). По сути, вы говорите, что я хочу соответствовать "???????" или ???????? [возврат каретки]

Конечно, вы получите апостроф, вы соответствовали ему. Тебе придется скинуть эти вещи.

patter = '/\s*'.$configname.'\s*\=\s*(\")(.*?)(?(1)\"|)\s*/'

...