Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!
Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.
Strony: 1
Witam
Mam kilka pytań dotyczących wyrażeń regularnych:
1. Czy jeśli chcę wyciać jakiś zakres tekstu, który wchodzi przez <STDIN>,
od słowa pierwszy w linni 3 do słowa ostatni w linni 289, to wyrażenia pierwszy$ i ^ostatni mogę umiescić w jendej regule - czy musze stosać jakieś obejście np.
dwie funkcje if , jak w przykładzie:
if ((m/(P|p)ierwszy$\n/)) { if (m/^ostatni/){
I jak taka konstrukcja (lub jakaś podobna) ma być skonstruowana, aby wyciągnąć fragment z ciągu (np. tekstu) tak, - jak na przykładzie:
Perl został zaprojektowany jako praktyczne narzędzie do analizy plików tekstowych i tworzenia raportów. Jednym z naczelnych haseł jest Można to zrobić na różne sposoby (ang. There is more than one way to do it – TIMTOWTDI – wymawiane jak Tim Toady). Jednym z podstawowych zamysłów projektu było uczynienie łatwych zadań łatwymi do wykonania, zaś trudnych – wykonalnymi. Wszechstronność Perla pozwala na programowanie w różnych modelach: proceduralnym, funkcyjnym czy obiektowym, chociaż purystom przeszkadza podejście polegające na przedkładaniu wygody programisty nad czystość projektu.
chodzi o wyciągnięcie (w tym przykładzie) wytłuszczonego fragmentu tekstu.
2.Jak wpisac w regułę wyrazenia, żeby ignorował znak końca linni \n i przepuszczał cały tekst od pierwszy do ostatni? (a nie linie zawierajace pierwszy i ostatni)
3. (Czy|jak) takie wyrażenie
awk -F':' '{print $1 $2 $3 $4 $5}'
można popełnić przez wyrażenie regularne? - jak powinno wyglądać?
(Bo nie zawsze jest pod ręką, lub w systemie, bash i awk).
Wielka prośba - nauka wyrażeń idzie mi niewiele lepiej niż chińskiego.
Jakby ktos mógł rzucić przykłady zapisu takich wyrażeń (podwójnego, czy zastępującego awk), było by wspaniale.
4. Czy znacie jakiś dobry program - do tworzenia i edycji wyrazeń regularnych, z kontrolą składni? - czy jest coś co zasługuje na uwagę, i dziala pod linuxem (ewentualnie pod wine), - godne polecenia?
Bo zainstalowałem kregexpeditor - cieszyłem się jak szczur na otwarcie kanału,
a tu lipa - można wpisać z palca wyrażenie regularne - wyrysuje mapkę, ale edycja całości nie działa.
Znalazłem też program regex-coach - ale zamiast się uruchomić sypie błędami.
Natomist Pyred - jeszcze jeden, nie zamierza się skompilować (jest w pythonie), też błędy.
Dzięki i Pozdrawiam
;)
Ostatnio edytowany przez Jacekalex (2010-03-09 12:14:00)
Offline
odpowiem w Twoim stylu:
Hasło "wyrażenia regularne" - na Wikipedii nie występuje?
tylko, ze ja nie ponize sie do Twojego poziomu i podam Ci linki z dokumentacja i wyjasnieniem do wyrazen regularnych a reszte to sam sobie wyjasnij
http://pl.wikibooks.org/wiki/Perl/Opis_wyra%C5%BCe%C5%84_regularnych
http://pl.wikibooks.org/wiki/Perl/Wyra%C5%BCenia_regularne
Offline
Na wikipedii przestudiowałem wszystko bardzo dokładnie.
Ale w tamtych przykładach, tak samo, jak w książce Perl Wprowadzenie - helionu, którą mam przed nosem, takie przypadki też nie są dokładnie wyjaśnione.
Wszedzie są tylko regułki i podstawy ogólne. We wszystkich materiałach, jakie przeczytałem, nie znalazłem ani jednego słowa o takich błahostkach, jak wprowadzenie pojęcia ignorowanie znaku nowej linni w wyrażeniu regularnym, nie znalazłem też sposobu, aby usunąć jakiś fragment ciągu z ciągu znaków takim wyrażeniem.
A szukałem nie tylko na wikipedii.
Kłopot wszystkich poradników, jakie widziałem polega na tym, że tam nie napisali, o czym zapomnieli napisać.
Może ja jestem ślepy, ale pytam o to, cze go na wiki, w wkilku ebookach, i innych poradnikach nie znalazłem.
I nie tylko w odniesieniu do perla, ale sprawdzalem też tematykę wyrażeń regularnych w odniesieniu do javy, php, pythona i C/C++.
I wszędzie widzę albo ogólnikowe przykłady, jak ten z wikipedii:
$string1 = "Hello World\n"; if ($string1 =~ m/l+/) { print "Występuje jedno lub więcej liter l obok siebie w $string1\n"; }
- ale ani on, ani kilka innych na tej stronie tematu nie wyczerpuje.
Wszedzie widzę takie przykłady bardziej nadające się bardziej do przedszkola, niż do prawdziwego zastosowania, przy analizowaniu danych wczytywanych z <STDIN>, czy wczytywanych z pliku.
Dziękuję za "pomoc."
To by było na tyle.
Ostatnio edytowany przez Jacekalex (2010-03-08 16:07:47)
Offline
Podałbyś przykładowy kod.
<STDIN> czyta od początku do znaku który zawiera zmienna $/ (domyślnie \n, czyli znak nowej linii) włącznie.
Istnieją dwa sposoby jego wykorzystania: przypisanie do zmiennej lub osadzenie w pętli. Właściwie przypisanie do zmiennej jest dość bezwartościowe, ponieważ nie zapewnia żadnego prostego sposobu sprawdzania poprawności otrzymanych danych (zawsze trzeba zakładać że użytkownik nie wpisze tego o co się go prosi).
Osadzenie w pętli może wyglądać tak:
while (<STDIN>) { // zrób coś ze zmienną }
Do pętli można wrzucić np. push (@array, $_);, co powoduje dodanie zmiennej do tablicy.
Tablica składa się ze zmiennych (scalar).
Nie ma sposobu by wyrażeniem regularnym ogarnąć wszystkie zmienne w tablicy. Dlatego trzeba najpierw połączyć wszystkie zmienne w tablicy w jedną zmienną, np. w ten sposób:
my $new_scalar; $new_scalar .= $_ foreach (@array);
Alternatywnie można od tego zacząć i przy przetwarzaniu danych z wejścia dodawać je do zmiennej:
my $scalar; do { $scalar .= <STDIN>; } until ($scalar =~ m/ostatni/);
Należy pamiętać że zmienna nie równa się linii — zmienna może zawierać znak nowej linii, w regexpie zapisywany jako \n.
Offline
Dzięki
Taki przykład:
to jest text:
Perl został zaprojektowany jako praktyczne narzędzie do analizy plików tekstowych i tworzenia raportów. Jednym z naczelnych haseł jest Można to zrobić na różne sposoby (ang. There is more than one way to do it – TIMTOWTDI – wymawiane jak Tim Toady). [b]Jednym z podstawowych zamysłów projektu było uczynienie łatwych zadań łatwymi do wykonania, zaś trudnych – wykonalnymi. Wszechstronność Perla pozwala na programowanie w różnych modelach: proceduralnym, funkcyjnym czy obiektowym[/b], chociaż purystom przeszkadza podejście polegające na przedkładaniu wygody programisty nad czystość projektu.
a wytłuszczone do wyciągnięcia.
Skrypt "laboratoryjny" wyglada np. tak:
#!/usr/bin/perl use strict; my $zmienna=""; while (<>) { if (/Jednym.z.p.*?obiektowym//) { $zmienna .= $_;{ print "$zmienna\n" } } }
W warunku wyrażenia regularnego próbowałem chyba z 50 - czy 100 różnych kombinacji (mam na myśli tylko takie, przy których perl nie wywalał błędów w składni)
i w najlepszym razie udało mi się coś odfiltrować, nigdy w granicach zapotrzebowania.
Jedno o czy sie przekonałem z całą pewnością:
Wszytkie poradniki, które nie zaierają działającego czytelnego przykładu, jak z ciągu STDIN (lub zmiennej) wyciągnąć to, co (następuje po|rozpoczyna się) wyrażeniem argument
na nic mi sie nie przydały, tak samo jak wszystkie, które nie objęły takim przykladem końca wyciętego fragmentu np:argumentost - jako argumentu.
A znacznikow ^ i $ próbowałem na wszelkie możliwe sposoby.
Też we wszystkich można wyczytać, ze znak \n oznacza nową linię,(co wiem do kilku lat), ale jak ustawić polecenie ignorowania znaku nowej linni, nie znalazłem nigdzie (działającego)
A to jest kluczowe dla mnie, bez względu na to - czy trzeba wyciągnąć jedno wyrażenie, czy liczbę z dokumentu (czy STDIN), czy trzeba wyciągnać 200 linni tekstu od pierwszego przecinka, do ostatniego znaku zapytania.
Moze ja jestem ślepy, może brak mi doświadczenia, ale widzę jeden problem wszystkich poradnikow, - niedomówienia.
Tam po prostu nie napisali, o czym zapomnieli napisać.
Na szczęście - nie robię tego do roboty, na termin, ale muszę się szybko takich sposobów nauczyć, bo kroi mi się w robocie (w zarysach), koniecznośc rozwiązania, które będzie takich filtrów wymagało.
Pozdrawiam
Ostatnio edytowany przez Jacekalex (2010-03-09 08:15:20)
Offline
Jacekalex napisał(-a):
Wszytkie poradniki, które nie zaierają działającego czytelnego przykładu, jak z ciągu STDIN (lub zmiennej) wyciągnąć to, co (następuje po|rozpoczyna się) wyrażeniem argument
na nic mi sie nie przydały, tak samo jak wszystkie, które nie objęły takim przykladem końca wyciętego fragmentu np:argumentost - jako argumentu.
perldoc perlre, szukaj backreferences.
Jacekalex napisał(-a):
A znacznikow ^ i $ próbowałem na wszelkie możliwe sposoby.
Ponieważ ^ dopasowuje się do początku ciągu znaków, a $ jego końca. Ciągiem znaków jest cała wartość zmiennej.
Jacekalex napisał(-a):
Taki przykład:
to jest text:Kod:
Perl został zaprojektowany jako praktyczne narzędzie do analizy plików tekstowych i tworzenia raportów. Jednym z naczelnych haseł jest Można to zrobić na różne sposoby (ang. There is more than one way to do it – TIMTOWTDI – wymawiane jak Tim Toady). [b]Jednym z podstawowych zamysłów projektu było uczynienie łatwych zadań łatwymi do wykonania, zaś trudnych – wykonalnymi. Wszechstronność Perla pozwala na programowanie w różnych modelach: proceduralnym, funkcyjnym czy obiektowym[/b], chociaż purystom przeszkadza podejście polegające na przedkładaniu wygody programisty nad czystość projektu.a wytłuszczone do wyciągnięcia.
Skrypt "laboratoryjny" wyglada np. tak:Kod:
#!/usr/bin/perl use strict; my $zmienna=""; while (<>) { if (/Jednym.z.p.*?obiektowym//) { $zmienna .= $_;{ print "$zmienna\n" } } }
Właśnie przez taki kod niektórzy rozwijają perl do Pathologically Eclectic Rubbish Listener.
perl ma niezwykłą zdolność do domyślania się co właściwie się od niego oczekuje, dzięki czemu kod może być znacznie krótszy. Jednak przez to nieczytelny dla innych niż fachowcy, a w ekstremalnych przypadkach innych niż sam autor. Korzystanie z perlowej zdolności do domyślania się z kontekstu ma pewną wartość, i można ją wykorzystywać podczas pisania szybkich skryptów wg zasady „napisz, użyj i zapomnij” tudzież zabawy w golfa, ale w zastosowaniach produkcyjnych powinno się wszystko robić explicite — tak aby osoba która obejmie kod po Tobie wiedziała co i gdzie się dzieje.
W tym kodzie nie ma żadnego warunku który by przerywał pętlę pobierania danych z STDIN.
To co chcesz osiągnąć można rozwiązać np. tak:
#!/usr/bin/perl use strict; use warnings; my $zmienna=<STDIN>; # pobiera linię tekstu od użytkownika print "pobrany tekst:\n" . $zmienna; # drukuje otrzymany tekst if ($zmienna =~ m/^.+(jednym.*?obiektowym)/i) { print "fragment tekstu:\n". $1 . "\n"; # drukuje fragment otrzymanego tekstu zgrupowanego w nawiasach } my $nowa_zmienna = $zmienna; $nowa_zmienna =~ s/^.+(jednym.*?obiektowym)/$1/i; #perldoc perlop, s/// print "Alternatywnie fragment tekstu:\n" . $nowa_zmienna . "\n";
Zauważ że cały tekst rozpoczyna się od słowa „Jedynie”, więc chcąc mieć pewien określony tekst ze środka, trzeba wziąć to pod uwagę. Ale to już nie perl a regexpy jako takie.
Offline
Dzięki stókrotne!
Nareszcie działa jak powinno.
W nauce regexu jestem o lata świetlne do przodu.
Dokładnie o to chodziło. Działa podrecznikowo?
Pozostaje tylko jeden drobiazg.
Bo w tej chwili działanie sprawdza się idealnie w przypadku, gdy nie trafi na znak nowego wiersza, wtedy przerywa działanie.
Dziękuję bardzo.
Pozdrawiam
Ostatnio edytowany przez Jacekalex (2010-03-09 16:08:21)
Offline
Jacekalex napisał(-a):
Bo w tej chwili działanie sprawdza się idealnie w przypadku, gdy nie trafi na znak nowego wiersza, wtedy przerywa działanie.
Nie trafi na znak nowego wiersza gdzie?
Jeśli w pobieraniu danych od użytkownika, to jest to oczywiste. Pisałem w pierwszym moim poście jak ustawić inny znak (lub ich serię) mający być terminatorem dla danych otrzymywanych ze standardowego wejścia. Jednak ta metoda ma tę wadę, że ciąg ten zostanie dołączony do otrzymanego ciągu — przez co ewentualnie może być konieczne jego usunięcie. Niżej przedstawiam metodę bez tej wady.
Jeśli chodzi o znak nowego wiersza w regexpie, to odsyłałem Cię do perldoc perlre w poprzednim poście. Na samym początku masz:
s Treat string as single line. That is, change "." to match any character whatsoever, even a newline, which normally it would not match.
Rozwiązanie obu problemów:
#!/usr/bin/perl use warnings; use strict; my $tekst; while (my $var = <STDIN>) { last if ($var =~ m/koniec/); $tekst .= $var; } print "wprowadzony tekst:\n" .$tekst . "--------------\n"; if ($tekst =~ m/(jednym.*?obiektowym)/is) { print "fragment tekstu:\n". $1 . "--------------\n"; }
Offline
Dzięki, ale ze znakiem nowego wiersza poradziłem sobie samodzielnie, chwile po napisaniu tego pytania.
Wystarzyło go wstawić w takiej formie:
($zmienna =~ m/^.+(jednym.*?(\n*?).*?obiektowym)/i)
mam nadzieję, że niezbyt lamerskiej, i że ta zmiana nie kwalifikuje się do: Pathologically Eclectic Rubbish Listener.
Nie wiem dlaczego, ale w poprzednim prykładzie samo zaznaczenie znaku kropki nie dało porządanego efektu.
Teraz jest ok.
Pozdrawiam
Ostatnio edytowany przez Jacekalex (2010-07-22 08:49:25)
Offline
Jacekalex napisał(-a):
Nie wiem dlaczego, ale w poprzednim prykładzie samo zaznaczenie znaku kropki nie nało porządanego efektu.
Zakładam że nie jesteś głupi ani złośliwy, tylko po prostu nie znasz wcale lub znasz kiepsko język angielski. Jeśli mam rację, to będzie to pewnym problemem — większość dostępnej dokumentacji jest napisana właśnie w tym języku. Angielski jest również obowiązującym językiem na perlMonks, gdzie została już poruszona i rozwiązana spora część z problemów na które możesz się natknąć.
Myślę że w takim razie dobrym pomysłem będzie kupienie jakiejś książki o perl-u wydanej przez helion. „perl. Wprowadzenie” czy coś w tym guście (zakładam że takie coś istnieje — nie chciało mi się sprawdzać). Książki tego wydawnictwa, będące tłumaczeniami tych z wydawnictwa O'Reilly (charakterystyczne czarno-białe okładki z rysunkami zwierząt), są dość wysokiej jakości i mogę je polecić.
A wracając do problemu: dlatego, że domyślnie kropka zastępuje każdy znak oprócz znaku nowej linii. Zachowanie to można zmienić poprzez dodanie modyfikatora s za ostatnim delimiterem regexpa (delimiterem domyślnie jest ukośnik (/) ale można go zastąpić; ja preferuję dwukropki, które znacznie rzadziej niż ukośniki występują w stringach, dzięki czemu rzadziej trzeba je cytować poprzez poprzedzenie odwróconym ukośnikiem).
Twoje rozwiązanie jest stosunkowo dobre (spełnia postawione przed nim zadanie), jednak nadmiarowe. W tym kontekście dodanie modyfikatora s jest znacznie lepszym pomysłem.
Offline
Strony: 1