Vala регулярное выражение с использованием групп с подгруппами продолжает заканчиваться ошибкой сегментации - PullRequest
0 голосов
/ 24 ноября 2018

Это действительно просто.Я пытаюсь использовать регулярное выражение для идентификации определенных значений свойств в строке строки vcard.

Итак, вот код:

int main(string[] args){

string input = "TEL;VALUE=uri;PREF=1;TYPE=\"voice,home\":tel:+1-555-555-5555;ext=5555";



string regString = "(tel:(?<phnum>.*);)*(?<pref>PREF=1;)*";

Regex regex = new Regex(regString);
MatchInfo match;

regex.match(input_end, 0, out match);

stdout.printf(match.fetch_named("phnum"));

stdout.printf(match.fetch_named(pref));

return 0;

}

Что я хочуна самом деле это означает, что тег phnum применяется к подгруппе символов, когда он появляется на входе (следовательно, *, снаружи группы).поэтому, когда я делаю: match.fetch_named("phnum"), возвращаемое значение будет: "+ 1-555-555-5555".

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

Ответы [ 4 ]

0 голосов
/ 24 ноября 2018

Существует ряд вещей, которые можно сделать, чтобы улучшить код Vala:

  • Привязка GLib Regex к PCRE вернет сообщение об ошибке, содержащее некоторые сведения о недопустимом регулярном выражении.В Vala это сообщение можно прочитать, поместив new Regex () в блок try...catch.
  • regex.match() возвращает true, когда совпадение найдено, поэтому перенос regex.match() в оператор if делаетболее надежная программа
  • В Vala есть оператор объединения нулей ??, который является удобным способом предоставления альтернативного значения при наличии нулевого значения
  • MatchInfo имеет next() метод и в сочетании с циклом do {} when () Вала дает хороший способ безопасного извлечения нескольких совпадений

Используемое регулярное выражение должно исключать завершающий символ, ;.Таким образом, tel:(?<phnum>[^;|.]*); будет соответствовать всем символам, кроме ; после tel: до достижения ;.

Вот рабочий пример, объединяющий все это:

int main () {

  string input = "TEL;VALUE=uri;PREF=1;TYPE=\"voice,home\":tel:+1-555-555-5555;ext=5555";

  string regString = "tel:(?<phnum>[^;|.]*);|PREF=(?<pref>[0-9]*);";
  Regex regex;
  MatchInfo match;
  try {
    regex = new Regex(regString);
    if (regex.match(input, 0, out match)) {
      do {
        stdout.printf("Phone number: %s\n", match.fetch_named("phnum") ?? "None");
        stdout.printf("Preference: %s\n", match.fetch_named("pref") ?? "None");
      }
      while (match.next());
    }
  }
  catch (Error error) {
    print (@"$(error.message)\n");
    return 1;
  }

  return 0;
}

Это выводит:

Phone number: 
Preference: 1
Phone number: +1-555-555-5555
Preference: None

Есть два матча.Что интересно, первое совпадение возвращает пустую строку для номера телефона.Это потому, что это допустимый подшаблон, но ничего не соответствует.Почему pref является нулевым для второго матча, мне неясно.Это требует дополнительного изучения того, что происходит в движке регулярных выражений, но, надеюсь, этого достаточно, чтобы продолжить.

0 голосов
/ 24 ноября 2018

printf сначала принимает строку формата.Вам нужно изменить их на:

stdout.printf("%s\n", match.fetch_named("phnum"));

stdout.printf("%s\n", match.fetch_named("pref"));

Если строка формата равна нулю, printf будет иметь ошибку по умолчанию.

Если вы не хотите беспокоиться о строке формата, вы можетеиспользуйте FileStream.puts, но вам все еще нужна нулевая проверка:

if (match.fetch_named("phnum")!=null)
  stdout.puts(match.fetch_named("phnum"));
0 голосов
/ 24 ноября 2018

В предположении regex.match(input_end также должно быть regex.match(input

Без учета точного формата телефонного номера, одним из возможных решений может быть сопоставление разрешенных символов в классе символов и получить значение из группы с именем phnum

tel:(?<phnum>[0-9+-]+)

Regex demo | Протестируйте его онлайн

Или более широкое совпадение может заключаться в использовании отрицательного класса символов [^ для сопоставления с тем, что вам не нужно, и получения значения из группы с именем phnum

tel:(?<phnum>[^\r\n;]+)

Regex demo

0 голосов
/ 24 ноября 2018

Ваше регулярное выражение должно быть сокращено до:

tel:(?<phnum>.*);$

Теперь 'phnum' Группа будет содержать номер телефона.

...