Regular expressions


0

Здравейте,

 

Днес покрай дневните таскове исках да автоматизирам един процес, но изпаднах в затруднение с разбрабването на regula expression. Изполвам powershell, като целта е чрез cmdlet gc(get-content) се прочита съдържанието. Целта е резултата така да се обработи, че не зависимо ог контента в текстовия файл да търси:

ХХХХХХХХ-ХХХХ-ХХХХ-ХХХХ-ХХХХХХХХХХХХ

Използвах какви ли не стратегии и имам частичен резултат. На местата на Х може да има стойности A-Z, a-z, 0-9 

В моя случай информацията е от вида и на един ред на различни места:

Mailbox:Е4DF9A21-B89B-4D60-B0B6-1005F7AB4141 (Valentin Tsvetkov) 

Успях да докарам работещ вариант с:

$temp = gc temp.txt |? {$_ -match "x:\w+-\w+-\w+-\w+-\w+"}

това ни хваща всички елементи но във вида

 

Mailbox:Е4DF9A21-B89B-4D60-B0B6-1005F7AB4141 (Valentin Tsvetkov) 

След това пък става трудно да се маха инфото в скобите, защото е различно и може да има символи като запетая и други. Опитах се да намеря паттерн по който просто да дам изтрие всичко след последния Х, но уви без успех.
Целта е да се вземе само информацията в Х местата + "-" 

Пробвах с:
$temp = gc temp.txt |? {$_ -match "\w{8}-\w{4}-\w{4}-\w{4}-\w{12}"} - пак прихваща целия ред. 
Ще се радвам ако някой идея как да стане expression-a :)
 
Поздрави,
Валентин Цветков



Отговори



0
Ползвай този сайт като си търсиш regex:
http://www.regexlib.com/Search.aspx?k=guid&AspxAutoDetectCookieSupport=1

Много рядко ще ти се наложи да напишеш някакъв регекс сам. Тея работи са бая смотани и гадни, тъй че не си струва да се занимаваш, ако можеш да го вземеш на готово.
Мисля, че това ще ти свърши работа за да изкараш всичките съвпадения на regex-а в стринга:
http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.matches.aspx

Не съм ги тествал лично само съм ти ги изкарал от google , но ми изглежда , че трябва да работят ;).
Друг вариант е просто да го отрежеш отзад и отпред :).



0
Мерси за идеите. Тези които са в първия линк не стават. :) Тези с метод-а ще се поиграя малко по-късно.

от v_tsvetkov (0 точки)


0

Задълижтелно ли е да го правиш с регулярен израз. В сми ако входящият стринг винаги ти започва с "Mailbox:", можеш да направиш Split() и после Substring(); Примерно:

string input = "Mailbox:Е4DF9A21-B89B-4D60-B0B6-1005F7AB4141 (Valentin Tsvetkov)";
 
string[] temp = input.Split();
 
string result = temp[0].Substring(8);

 

PS: А ако и дължината на кода ти е фиксирана направо input.Substring(8, 36);


от gercho (851 точки)


0
Има нещо вярно, но ако му се наложи някой ден да смени pattern-а на емайла, ще трябва да се досети, че вътре е имал си шитня дето реже първите 10 и последните 30 символа и т.н. ;) Не е много професионално. По правило, никога нет рябва да разчиташ на нещо, което го вижда потребителя, тъй като front end-а винаги може да се смени.


0
Така е, просто в C# не съм много в час с регулярните изрази. Не исках да подведа колегата с решение, за което не съм сигурен, като същевременно се опитах да помогна. А иначе патерна ако се смени е възможно също така да се наложи промяна и на самият регулярен израз. ;-)

от gercho (851 точки)



0
Ето един цитат от Въведение в програмирането с C#.
"По-конкретно препоръчваме да посетите сайтовете http://www.regular-expressions.info/ и http://regexlib.com/. Повече информация за класовете, които .NET Framework предлага за работа с регулярни изрази и как точно се използват, може да бъде открита на адрес: http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex%28VS.100%29.aspx."

от iliyan.tanev (517 точки)


1
Не съм чел в детайли, но най-честата грешка при регилярните изрази е да пропуснаш ^ в началото и $ в края. Ако го направиш, може да ти хваща разни низове, които не са по шаблона, който си задал.

от svetlin.nakov (31978 точки)


0
Светльо прав си, но нещо на практика с ^ и $ не работи както се очаква. Примерно " {$_ -match "^\w+-\w+-\w+-\w+-\w+$"}" това не го хваща въобще. Аз за момента намерих workaround. С {$_ -match "x:\w+-\w+-\w+-\w+-\w+"} хващам това обаче: Mailbox:Е4DF9A21-B89B-4D60-B0B6-1005F7AB4141 (Valentin Tsvetkov) и после с цикъл и -replace махам излишните неща, но така и не успях да направя регулярен израз който от безразборен текст да мачва само GUID-a. :) Ще си поиграя още пък ще видим :)

от v_tsvetkov (0 точки)


0
Първо: Това не е GUID "Е4DF9A21-B89B-4D60-B0B6-1005F7AB4141" . От тука сигурно ти идва едната грешка. Пробвай се да го парснеш към гуид и виж, че ще ти даде грешка. Не съм съвсем уверен, кое точно в него не му харесва Guid парсъра, но пък може малко по-внимателно да видиш и да прочетеш :), сигурно е очевидно.

Второ: Ето ти работещ пример:
string pattern = @"[A-Za-z0-9]{8}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{12}"; Regex rgx = new Regex(pattern); string sentence = "ABC" + Guid.NewGuid().ToString() + " (Valentin Tsvetkov) "; string guid = "Е4DF9A21-B89B-4D60-B0B6-1005F7AB4141"; foreach (Match match in rgx.Matches(sentence)) Console.WriteLine("Found '{0}' at position {1}", match.Value, match.Index);
Също така трябва да махнеш $ и ^ отпред и отзад, защото тогава не ти хваща Guid вътре в стринг, а просто проверяваш , дали даден стринг е Guid , а това не ти върши работа. За това не трябва да ги ограничаваш с $ и ^ . Разбра ли :)? А не са ти работили regex -те които ти дадох, защото там всички ползват $ и ^ и мачват само Guid стрингове , а не Guid В string. Просто трябва малко да го модефицираш.



0
Между другото само да уточня, че явно това не ми излиза при мен като Guid заради копи пействането от форума във VS и сигурно се е прецакал при мен енкодинга на символите :), но го имай в предвид. А иначе останалото , което ти казах е вярно.



0

Хаха,

 

Да прав си колега но нека да поясня нещо. Guid-a за който аз писах беше е mailbox Guid и по скоро целта ми беше за работещ регулярен израз.

Тествах твоя в пайплайна на powershell:

gc temp.txt |? {$_ -match "[A-Za-z0-9]{8}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{12}"}


Но  ми връща следния резултат:

 

Mailbox:6CFAAC73-2DAF-4A5B-A1F2-C5E179170308 (ХХХХХХ ХХХХХХ)
Mailbox:6001BD46-E77D-416A-BF76-4D2A10C9AEE0 (ХХХХХХ  ХХХХХХ)
Mailbox:3E1EE82B-A7C4-4879-810B-A1173AC1C5E4 (ХХХХХХХХХХХХ)
Mailbox:4964A5BA-23E5-41CC-B738-6C1E087AFB28 (ХХХХХХ ХХХХХХ)
Mailbox:A2CAB18F-DD19-4DCF-9A20-35C44AE16AFA (ХХХХХХ ХХХХХХ)
Mailbox:32B7E06B-84BF-451E-ACA0-23F28B5D6897 (ХХХХХХ ХХХХХХ)
....
 
Реално това е същия резултат като от моя израз:
gc temp.txt |? {$_ -match "х:\w+-\w+-\w+-\w+-\w+"}  
 
\w+ е същото като A-Za-z0-9

Офф тъкмо забелязах нещо, което явно аз не съм интерпретирал добре. Регулярния израз работи, но -match винаги търси true or false и в крайна сметка на дадения ред ако е true  то показва неговата стойност от стринг-а, т.е. драмата ми е в оутпут-а който дава а не в намирането на инфото :) 
 

от v_tsvetkov (0 точки)


0
И ето го крайния резултат :)
Select-String -Path c:\temp\temp.txt -Pattern '[A-Za-z0-9]{8}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{12}' -AllMatches |%{$_.Matches}|%{$_.Value}
И другия работи също
Select-String -Path c:\temp\temp.txt -Pattern '\w+-\w+-\w+-\w+-\w+' -AllMatches | %{$_.Matches}|%{$_.Value}
Благодаря на всички за идеите :)

от v_tsvetkov (0 точки)