usernamekiran Ответов: 1

Как мне выполнить неограниченный положительный lookahead до определенного символа в регулярном выражении?


Всем привет. Это опять же вопрос, связанный с Википедией. Есть такая штука под названием wikilink (выводим один заголовок, переходим к другой статье). Например, "[[станция метро|станция]]" будет отображаться как "станция", но приведет вас к статье "станция метро". И "[[Вин Джонс (регби)|вин Джонс]]" перенесет вас в Вин Джонс (регби)".

Я выполняю задачу поиска и замены, используя следующее регулярное выражение:
Match m = Regex.Match(ArticleText, @"\[\[[W]yn Jones]]");
if (m.Success) ArticleText = ArticleText.Replace("Wyn Jones", "Wyn Jones (rugby union)");


С помощью приведенного выше регулярного выражения мой инструмент (auto wiki browser - AWB) заменяет только "Wyn Jones" на "Wyn Jones (rugby union)".

То, что я хочу сделать, это преобразовать экземпляры, такие как [[Wyn Jones|W. Джонс]] к "[[вин Джонс (регбийный союз)]]". Для этого конкретного примера я могу использовать что-то похожее на:
Match m = Regex.Match(ArticleText, @"\[\[[W]yn Jones\|W. Jones\]\])");
if (m.Success) ArticleText = ArticleText.Replace("\[\[Wyn Jones\|W. Jones\]\]", "\[\[Wyn Jones (rugby union)\]\]");


Но как мне заменить то, что находится между "|" и "]]"? В данном примере это "W.Джонс"; но в следующем это может быть "вин Джей", я думаю, мы могли бы использовать
abc(?=xyz)
но я не знаю, как это сделать. В основном мы должны сказать программе, чтобы она искала "[[Wyn Jones", за которым следует"|", и заменяла все, что есть до "]]".

Любая обратная связь будет очень признательна.

Что я уже пробовал:

following is the entire code that I have created. Note that first 17 lines of the codes are embedded in the AWB itself, so my code begins with line 18. Also, I ran only the first module without second module, and it worked fine. Apparently module2 doesnt have any effect. The module1 changed [[Wyn Jones]] to [[Wyn Jones (rugby union)]], [[Wyn Jones (rugby union)]] remained unchanged, [[Wyn Jones (rugby union)|Wyn Jones]] also remained unchanged, [[Wyn Jones (rugby union)|rugby player]] also remained unchanged. All of this is intended, but [[Wyn Jones|rugby player]] remained unchanged as well. That should have been replaced as [[Wyn Jones (rugby union)|Wyn Jones]].

В очень простых словах: я хочу найти все [[Вин Джонс]], и [[Wyn Jones|(любые переменные слова)]], и они должны быть заменены на "[[Wyn Jones (rugby union)|Wyn Jones]]".

В настоящее время [[Wyn Jones]] обрабатывается, но не переменные. Чтобы достичь этого, мы сначала должны найти для [[УИН Джонс|, а затем мы должны сказать программе заменить [[Wyn Jones| and ]], и все, что происходит между этими двумя с "[[Wyn Jones (rugby union)|Wyn Jones]]". Чтобы выразить это еще проще, мы должны назвать A, а затем заменить термин A, B и все, что находится между этими двумя терминами, термином C.

AWB также поддерживает программы на языке C#. Так что это не обязательно делать в регулярном выражении. Программа на C# тоже может работать.



public string ProcessArticle(string ArticleText, string ArticleTitle, int wikiNamespace, out string Summary, out bool Skip)
	{
		Skip = false;
		Summary = "fixed disamb link(s)";

			ArticleText = CustomModule1(ArticleText, ArticleTitle, wikiNamespace, ref Summary, ref Skip);
			ArticleText = CustomModule2(ArticleText, ArticleTitle, wikiNamespace, ref Summary, ref Skip);
//25
		return ArticleText;
	}

public string CustomModule1(string ArticleText, string ArticleTitle, int wikiNamespace, ref string Summary, ref bool Skip)
	{
		if (!Skip)
			{
			Summary = "fixed disamb link(s)";
//34
			Match m = Regex.Match(ArticleText, @"\[\[[W]yn Jones]]");
			if (m.Success) ArticleText = ArticleText.Replace("[[Wyn Jones]]", "[[Wyn Jones (rugby union)]]");
			else ArticleText += "";
			}
		return ArticleText;
	}
//41 apparently custom module 2 doesnt have any effect on this.
public string CustomModule2(string ArticleText, string ArticleTitle, int wikiNamespace, ref string Summary, ref bool Skip)
	{
    		if (!Skip)
			{
			Summary = "fixed disamb link(s)";
//47
			Match m = Regex.Match(ArticleText, @"\[\[[W]yn Jones\|");
			if (m.Success) ArticleText = Regex.Replace(ArticleText, @"[[Wyn Jones\[[Wyn Jones|, ]]}", "[[Wyn Jones|Wyn Jones (rugby union)]]", RegexOptions.IgnoreCase);
			
	}
		return ArticleText;
}

1 Ответов

Рейтинг:
2

OriginalGriff

Попробовать это:

(?<=\[\[Wyn Jones)\|.*?(?=\]\])

Это относится к нужному вам имени как к "игнорируемому префиксу", а Терминатор-как к "игнорируемому суффиксу", поэтому '|' вплоть до последнего символа перед первым ']' будет заменен.


usernamekiran

Привет. С помощью вашего кода я создал это:

public string ProcessArticle(string ArticleText, string ArticleTitle, int wikiNamespace, out string Summary, out bool Skip)
	{
		Skip = false;
		Summary = "test";
			Match m = Regex.Match(ArticleText, @"\[\[[W]yn Jones]]");
			if (m.Success) ArticleText = Regex.Replace("(?<=\[\[Wyn Jones)\|.*?(?=\]\])", "[[Wyn Jones (rugby union)]]");
			else ArticleText += "";

		return ArticleText;
	}

Но это дает мне ошибку "[CS1009] Unrecognized escape sequence", где бы мы ни использовали \ для побега. Я тоже пытался:
public string ProcessArticle(string ArticleText, string ArticleTitle, int wikiNamespace, out string Summary, out bool Skip)
	{
		Skip = false;
		Summary = "test";

			Match m = Regex.Match(ArticleText, @"\[\[[W]yn Jones]]");
			if (m.Success) ArticleText = ArticleText.Replace("(?<=\[\[Wyn Jones)\|.*?(?=\]\])", "[[Wyn Jones (rugby union)]]");
			else ArticleText += "";            
		return ArticleText;
	}

Он выдал ту же ошибку. Удивительно, но страница регулярных выражений AWB выдает один и тот же метод экранирования по адресу: https://en.wikipedia.org/wiki/Wikipedia:AutoWikiBrowser/Regular_expression

Что я делаю не так?

usernamekiran

Я также попробовал этот код (с "Regex.Replace", а также все та же ошибка:

public string ProcessArticle(string ArticleText, string ArticleTitle, int wikiNamespace, out string Summary, out bool Skip)
	{
		Skip = false;
		Summary = "test";

			Match m = Regex.Match(ArticleText, @"\[\[[W]yn Jones]]");
			if (m.Success) ArticleText = ArticleText.Replace("(?<=\[\[Wyn Jones)\|.*?(?=\]\])", "[[Wyn Jones (rugby union)]]", RegexOptions.IgnoreCase);												
			else ArticleText += "";

		return ArticleText;
	}

usernamekiran

Следующий код был скомпилирован, но он не внес никаких изменений в вышеупомянутые отредактированные примеры.

public string ProcessArticle(string ArticleText, string ArticleTitle, int wikiNamespace, out string Summary, out bool Skip)
	{
		Skip = false;
		Summary = "test";
			Match m = Regex.Match(ArticleText, @"\[\[[W]yn Jones]]");
			if (m.Success) ArticleText = ArticleText.Replace(@"(?<=[[Wyn Jones)\|.*?(?=]])", "[[Wyn Jones (rugby union)]]");
			else ArticleText += "";

		return ArticleText;
	}

OriginalGriff

Значит, ты не слишком внимательно прочитал то, что я сказал?
'[', '] 'и' | ' - это все специальные символы в регулярных выражениях, и поэтому их необходимо экранировать, если вы хотите сопоставить их как текст ...

OriginalGriff

Сделайте себе одолжение, и получите копию Экспрессо[^] - это бесплатно, и он проверяет и генерирует регулярные выражения.
Введите в него текст статьи в качестве текстовых данных и попробуйте заменить строки.
Посмотрите, что происходит, и он может генерировать код C#, который вы можете вставить непосредственно в свое приложение, когда оно заработает.