[Homework]C# Advanced - Regular Expression- Problem {2}
Здравейте може ли малко помощ по задачата.
Здравейте може ли малко помощ по задачата.
По мое мнение ще е най-добре лично да се поблъскаш над задачата, но с идея че аз не помня да са ни преподавали това в лекцията, ще ти препоръчам да погледнеш Regex Substitutions в MSDN. Също така както казаха този сайт https://regex101.com/ е много полезен.
Ще опитам да дам насоки за решаване без да давам готово решение.
Както е казано по условие, един валиден линк таг е във формат: "<a href=[link]>[text]</a> ". Имаше в текста на условието сложени някакви кавички, които в примера ги няма. Игорирайте го, ще го поправим, за да не се обърквате излишно.
За да сте сигурни, че работите с валидни тагове, трябва да мачнете текста с регулярен израз, който хваща целите тагове до края им. Задължителните части на тага може да се напишат в регекса буквално (тези, които не са болднати в примера по-горе). Линкът и тестът са малко по-особени; там трябва просто да кажем, че искаме да имаме някаква поредица от символи, но трябва да спрем ако стигнем до '>' (за линка) и '<' (за текста).
По-трудният вариант е да се заместват само а-тата и триъгълните скоби. Изглежда всеки първоначално започва да мисли в тази насока, изглежда по-пестеливо (помня, че и аз се мъчих с подобна логика преди време). Трудно е обаче да кажеш "махни ми символите '<', ама само тия, които са част от валиден таг".
По-лесно е, веднъж след като един таг е намерен, целият да се замени с нов таг, който е [URL href=[link]][text][/URL].
За да се създаде този заместващ текст, трябва по някакъв начин да сме получили данните за link и text, което се постига с групи в регулярния израз - ().
Да речем имам намерени някакви мачове. В група 0 на всеки един мач имам целия линк, който трябва да заменя. В други две групи имам данните за линка и текста, които мога да използвам, за да създам новия URL таг. И след това мога да ползвам Replace(), за да заместя оригиналния "а" таг с новия "URL".
string input ="<ul><li><a href=http:softuni.bg>SoftUni</a></li></ul>";
string pattern =@"[a]";
string replacement = "URL";
Regex reg = new Regex(pattern);
string result = reg.Replace(input, replacement);
Console.WriteLine(result);
За сега от мен е това.Просто заменям "а" с "URL" и от сутринта си тровя нервите със заменянето на кавичките.Ама за сега неуспешно
Ps: 3-та задача я направих точно за 10 мин/без да копирам/
Интересно лично на мене 3та ми се стори, една от по сложните да се направи правилно, би ли я постнал, интересно ми е да видя как си я решил.
// Write a program to extract all email addresses from a given text.
string text = Console.ReadLine();
string pattern = @"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";
Regex reg = new Regex(pattern);
MatchCollection matches = reg.Matches(text);
foreach (Match i in matches)
{
Console.WriteLine(i.Groups[0]);
}
След малко като се видим и ще ти кажа какво направих:)
Благодарение на поста на Filkolev май стигнах до работещо решение на 2ра задача. Кавичките съм ги махнал с "груба сила" дет се вика, но просто ме можах да се сетя как да ги вкарам в първия патерн.
Забравих да добавя, че входящия стринг е на един ред, а не както примера в домашното.
Edit2: Тъй като май няма тема за цялото домашно, качвам и едно решение на първа задача, и започвам трета
И аз се тормозя с тази задача, след като първата ми отне 2-3 часа.
До сега стигнах до правилния regex израз според regex101 - (<a href=)[a-z:\/.]*(>)\w*(<\/a>)
Като резултат на това получавам:
MATCH 1
1. [13-21] `<a href=`
2. [38-39] `>`
3. [46-50] `</a>`
точно това са частите от стринга, които искам да заменя. От тук нататък, обаче, нямам идея какво става. Опитах всичко, което се сетих да опитам, но без очаквания резултат.
Малко по-горе подсказах, че логиката е по-лесно ако се обърне - не да мачваш това, което искаш да замениш, а това, което искаш да запазиш. Опитай така да я пребориш.
Моето минималистично решение на задачата. Засега работи само с едноредов вход. Обработва href-атрибута независимо дали последният е в кавички или не.
Здравейте колеги!И аз стигнах до някакво решение на въпросната задача.FilKolev много добре е обяснил задачата и следвах стъпките.Ще са от полза препоръки и съвети.http://pastebin.com/aa7c8vcf
Малко е опасно това, което правиш в групите, в които хващаш линка и текста. Никъде не е казано, че ще са в такива формати (за линка казваш, че ще има 4 букви в началото например, за текста казваш, че ще е само от букви). Не знаеш например дали линкът няма да има символи като %, +; в тескта пък може да има много неща, не само букви.
Има два варианта за тези две групи. Единият е да се ползва (.*?), което хваща всичко без нови редове, като това е lazy, т.е. ще спре да мачва като стигнеш символите, които си посочил в регекса след тях - съответно '<' и '>'. Другият вариант е да ползваш за линка: ([^>]+), а за текста: ([^<]+).
Възможно най-краткото решение до което достигнах е:
string input = "<ul><li> <a href=http://softuni.bg>SoftUni</a> </li></ul>";
Console.WriteLine(input);
string pattern = @"<a(.*)<\/a>";
Regex regex = new Regex(pattern);
Console.WriteLine(regex.Replace(input, "[URL$1[/URL]"));
Възможни ли са някакви проблеми при този вариант?
Здравей, така написан кода не ти дава верен output.
Трябва да има
"]" , след " softuni.bg",
а при теб е ">".
Възможно е да хванеш невалидни тагове. Освен това (.*) е greedy, което значи, че ще хване възможно най-много символи, включително и други затварящи а-тагове. Тествай с този текст например:
<ul><li> <a href=http://softuni.bg>SoftUni</a> </li></ul></a>
Дам, прави сте и двамата - скобата не съм я видял. Много пипкава работа са тези регекси
След кратка модификация се получава това, което виждам че един колега по-горе e пуснал. Мисля че работи ОК.
string pattern = @"<a(.*?)>(.*?)<\/a>";
Regex regex = new Regex(pattern);
Console.WriteLine(regex.Replace(input, "[URL$1]$2[/URL]"));
Здравейте! Не знам до колко е верно , но ето и моето решение.Ще се радвам да чуя мнение.
string input = Console.ReadLine().Trim(); string pattern = @"(<a)(.*?)(>)(.*?)(<\/a>)"; var replaced = Regex.Replace(input, pattern, m => "[URL" + m.Groups[2].Value +"]"+m.Groups[4].Value+"[/URL]"); Console.WriteLine(replaced);
Здравейте, regular expressions за мен са нещо много ново. Не мога да разбера къде бъркам, но всичко което прави следният код е да направи от http - htp (маха едно t).
тествайки го v regex101, matchva vscihko коректно. Имам две групи, както трява... и т.н Кодът не е дълъг, така че го пействам тук:
ring userInput = Console.ReadLine();
string toReplace = @"(?<=>)<a\s+(href=[a-z]{4,5}:\/\/[a-z]+.[a-z]+)>([a-zA-Z]+)<\/a>(?=<)";
string replacement = "[URL $1]>$2[/URL]";
Regex pattern = new Regex(toReplace);
string result = pattern.Replace(userInput, replacement);
При мен работи коректно. Имам няколко препоръки относно самия регекс обаче.
Тези lookahead и lookbehind не са нужни, поставят някакви ограничения, които няма нужда да са там. Искаш около а-тага да имаш други, но това не е гарантирано, може да имаш празни места, а да не са слепени таговете.
Протокола си задал че е 4 или 5 символа, освен http и https има ли други, които искаш да хванеш? Ако няма, по-добре го мачни с https? - казваш, че искаш http, a s-a е опционален.
Силно ограничаваш мачовете като на доста места казваш, че искаш да има само букви, но ако вземеш няколко произволни адреса ще видиш, че може да има доста повече символи, включително цифри например. Тук е сложно да се направи съвсем коректно, но .*? хваща всичко и ще работи в повече случаи. Аз бих го сложил както за URL-a, така и за текста на линка. Дали е валиден линк - това трябва отделно да се провери в моя вариант, но ако целта е да хванеш валидни тагове това ще сработи и ще покрие повече варианти:
<a\s+(href="https?:\/\/.*?")>(.*?)<\/a>
Мерси за примера и препоръките. Изглежда доста по-събрано и лесно разбираемо.
Аз разбрах условието, че се търси точно този формат, но изглежда се има предвид генерално.
Рестартирах компютъра, написах го наново и проработи.
Мъча се от сутринта стигнах до тук:
string str = "<ul>\n<li>\n<a href=http://softuni.bg>SoftUni</a>\n</li>\n</ul>";
Console.WriteLine(Regex.Replace(str, @"a{1}", @"URL"));
//<URL href=http://softuni.bg>SoftUni</URL>
//[URL href=http://softuni.bg]SoftUni[/URL] (очаквано)
но това не е никакво решение.
Незнам как да вкарам "[]", вместо "<>".
Просто напиши регекса така че да засича всички части които искаш да смениш цялата идея на Regex Substitutiona e че като хванеш каквото ти трябва със регекса може да го смениш а Substitutiona ще ти запази другата част еднаква.
Моя регекс изглеждаше така
<код за хващане на "<a href="><non capturing (subexpression)><код за хващане на ">"> <non capturing(subexpression)><код за хващане на "</a>">
това цялото е един регекс.
идеята на това е че аз не искам регекса да хваща кода в non capturing subexpression-а защото всичко което регекса маркира ще го Replace-на, но все пак искам какво пише вътре с цел да го дръпна обратно в крайния си резултат със Substitution.
Препоръчвам ти да си отвориш презентацията и да преминеш пак Grouping Constructs, аз докато ги пиша тези регекси https://regex101.com/ и презентацията са ми постоянно отворени и ги ползвам за сверяване.
Edit: ок махнах някой работи, за да трябва да се помисли :).
$1 е референция към първата хваната група, $2 към втората и така нататък. В случая, ако измислиш патърн, който да хваща релевантната информация в две групи (заградени с кръгли скоби () : )), може да ползваш това.
text = pattern.Replace(text, "[URL$1]$2[/URL]")
$1 и $2 ще пазят важната за теб информация в случая.