Нечетные результаты сопоставления регулярных выражений модуля OCaml `Str` - PullRequest
0 голосов
/ 06 мая 2020

Когда я выполняю следующую тестовую программу:

let re = Str.regexp "{\\(foo\\)\\(bar\\)?}"

let check s =
    try
        let n = Str.search_forward re s 0 in
        let a = Str.matched_group 1 s in
        let b = Str.matched_group 2 s in
        Printf.printf "'%s' => n=%d, a='%s', b='%s'\n" s n a b
    with
        _ -> Printf.printf "'%s' => not found\n" s

let _ =
    check "{foo}";
    check "{foobar}"

, я получаю странные результаты. Т.е.:

$ ocaml str.cma test.ml
'{foo}' => не найдено
'{foobar}' => n = 0, a = 'foo' , b = 'bar'

Несовместима ли группировка с помощью \\( и \\) с оператором ?? В документации об этом не упоминается.

1 Ответ

2 голосов
/ 06 мая 2020

Для вашего первого примера нет совпадения с группой 2. Таким образом, вызов Str.matched_group 2 вызывает Not_found.

Чтобы получить более точные результаты, чем в вашей функции check, вам необходимо обработать каждая группа отдельно со своим блоком try. В принципе, любой вызов Str.matched_group может вызвать Not_found (в зависимости от свойств регулярного выражения и совпадающей строки).

Я переписал вашу функцию check следующим образом:

let check s =
    let check1 n g =
        try
            let m = Str.matched_group g s in
            Printf.printf "'%s' group %d => n = %d, match = '%s'\n"
                s g n m
        with Not_found ->
            Printf.printf "'%s' group %d => not matched\n" s g
    in
    let n = Str.search_forward re s 0 in
    check1 n 1;
    check1 n 2

Вот результат исправленного кода:

'{foo}' group 1 => n = 0, match = 'foo'
'{foo}' group 2 => not matched
'{foobar}' group 1 => n = 0, match = 'foo'
'{foobar}' group 2 => n = 0, match = 'bar'
...