LINUX.ORG.RU

Непонятки с glib regex

 ,


0

1

Нда... вот даже и незнаю как вопрос-то сформулировать. Нифига не работает! 2-й день бьюсь почти без результатно. Пытаюсь регэкспом найти в тексте римские цифры. Составил запрос, вот такой: "[IVXLM]+". Если в тексте нету перевода строк, то все работает нормально. Если есть \n (т.е. перевод LF), то регэксп по сути не работает, работой это назвать нельзя. Также пробовал с \r и c \r\n - результат тот же, не работает.

Пробовал использовать флаги G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_LF, G_REGEX_MATCH_NEWLINE_ANY и другие флаги конца строк. Результат работы регэкспа меняется, но не идеален.

В какую сторону рыть?

Если это важно, в тексте есть еще и табуляции \t. Текст в UTF-8. А закономерность работы регэкспа я, честно, не понимаю. Запрос "[IVXLM]+" выделяет так же некоторые русские буквы, чаще всего «а».

И более того!!!! Два запуска одного и того же бинаря дают разный результат работы! Нда...

Использую Vala.

★★★★★

Последнее исправление: CYB3R (всего исправлений: 3)
Ответ на: комментарий от baverman

Да код-то простой, мне кажется...

			try {
				var r = new Regex ("[IVX]+", RegexCompileFlags.NEWLINE_LF);
				MatchInfo mi;
				
				if (r.match (tb.text, RegexMatchFlags.NEWLINE_LF, out mi)) {
					do {	
						int sp, ep;
						mi.fetch_pos (0, out sp, out ep);
	
						TextIter begin_attr;
						TextIter end_attr;
	
						tb.get_iter_at_offset (out begin_attr, tb.text.char_count (sp) );
						tb.get_iter_at_offset (out end_attr, tb.text.char_count (ep));
	
						tb.apply_tag_by_name ("bold", begin_attr, end_attr);
						
		
					} while (mi.next ());
				}
			}
			catch (RegexError e) { stdout.printf ("Regex error\n"); }

hibou ★★★★★
() автор топика
Ответ на: комментарий от hibou

УМВР. vala 0.12

class Demo.HelloWorld : GLib.Object {

    public static int main(string[] args) {
	string text = "some русский text with VI \nand XI XXX\n\r XIV";

	var r = new Regex ("[IVX]+");
	MatchInfo mi;
				
	if (r.match (text, 0, out mi)) {
		do {
			int sp, ep;
			mi.fetch_pos (0, out sp, out ep);
			stdout.printf("%i %i\n", text.char_count(sp), text.char_count(ep));
		} while (mi.next());
	}
        return 0;
    }
}
baverman ★★★
()
Ответ на: комментарий от hibou

так про эту проблему ты уже спрашивал. и сам же решение находил.

mi.fetch_pos (0, out sp, out ep) дает тебе смешение в байтах

чтобы работать с textiters надо полученные указатели нормализовать при помощи g_utf8_pointer_to_offset (ну или какой там аналог в vala)

в качестве примера вот тебе работающая функция с аналогичной функциональностью

static void
linkify_cb (GtkTextBuffer *buf, GRegex *regex)
{
  gchar *text;
  GtkTextIter start, end;
  GMatchInfo *match;

  gtk_text_buffer_get_bounds (buf, &start, &end);
  text = gtk_text_buffer_get_text (buf, &start, &end, FALSE);

  gtk_text_buffer_remove_all_tags (buf, &start, &end);

  if (g_regex_match (regex, text, G_REGEX_MATCH_NOTEMPTY, &match))
    {
      do
        {
          gint sp, ep, spos, epos;

          g_match_info_fetch_pos (match, 0, &sp, &ep);

          /* positions are in bytes, not character, so here we must normalize it*/
          spos = g_utf8_pointer_to_offset (text, text + sp);
          epos = g_utf8_pointer_to_offset (text, text + ep);

          gtk_text_buffer_get_iter_at_offset (buf, &start, spos);
          gtk_text_buffer_get_iter_at_offset (buf, &end, epos);

          gtk_text_buffer_apply_tag (buf, tag, &start, &end);
        }
      while (g_match_info_next (match, NULL));
    }
  g_match_info_free (match);

  g_free(text);
}
ananas ★★★★★
()
Ответ на: комментарий от ananas

Да, ты прав. Но ты не совсем внимателен. Решение тут тоже применено. :)
string.char_count (int number_in_bytes) - принимает значение в байтах и возвращает значение в символах.

Вообще, код работает. Но через раз. На 3 запуска одного и того же бинарника - 2 запуска правильных и 1 неправильный. И я не понимаю почему так.

hibou ★★★★★
() автор топика
Ответ на: комментарий от hibou

попробуй перед do дернуть tb.remove_tag_by_name по всему буферу

ananas ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.