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!

Ogłoszenie

Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.

#1  2010-03-08 11:21:26

  Jacekalex - Podobno człowiek...;)

Jacekalex
Podobno człowiek...;)
Skąd: /dev/random
Zarejestrowany: 2008-01-07

[SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

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:

Kod:

 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

Kod:

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)


W demokracji każdy naród ma taką władzę, na jaką zasługuje ;)
Si vis pacem  para bellum  ;)       |       Pozdrawiam :)

Offline

 

#2  2010-03-08 15:25:48

  jezoo - Dzięcioł

jezoo
Dzięcioł
Skąd: Z lasu
Zarejestrowany: 2005-09-02

Re: [SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

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


LRU #480459

Offline

 

#3  2010-03-08 15:44:28

  Jacekalex - Podobno człowiek...;)

Jacekalex
Podobno człowiek...;)
Skąd: /dev/random
Zarejestrowany: 2008-01-07

Re: [SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

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:

Kod:

$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)


W demokracji każdy naród ma taką władzę, na jaką zasługuje ;)
Si vis pacem  para bellum  ;)       |       Pozdrawiam :)

Offline

 

#4  2010-03-08 21:06:12

  Minio - Użyszkodnik

Minio
Użyszkodnik
Skąd: Poznań, Polska
Zarejestrowany: 2007-12-22
Serwis

Re: [SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

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:

Kod:

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:

Kod:

my $new_scalar;
$new_scalar .= $_ foreach (@array);

Alternatywnie można od tego zacząć i przy przetwarzaniu danych z wejścia dodawać je do zmiennej:

Kod:

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

 

#5  2010-03-09 07:26:10

  Jacekalex - Podobno człowiek...;)

Jacekalex
Podobno człowiek...;)
Skąd: /dev/random
Zarejestrowany: 2008-01-07

Re: [SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

Dzięki

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 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)


W demokracji każdy naród ma taką władzę, na jaką zasługuje ;)
Si vis pacem  para bellum  ;)       |       Pozdrawiam :)

Offline

 

#6  2010-03-09 11:55:19

  Minio - Użyszkodnik

Minio
Użyszkodnik
Skąd: Poznań, Polska
Zarejestrowany: 2007-12-22
Serwis

Re: [SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

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:

Kod:

#!/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

 

#7  2010-03-09 12:12:56

  Jacekalex - Podobno człowiek...;)

Jacekalex
Podobno człowiek...;)
Skąd: /dev/random
Zarejestrowany: 2008-01-07

Re: [SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

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)


W demokracji każdy naród ma taką władzę, na jaką zasługuje ;)
Si vis pacem  para bellum  ;)       |       Pozdrawiam :)

Offline

 

#8  2010-03-09 21:41:36

  Minio - Użyszkodnik

Minio
Użyszkodnik
Skąd: Poznań, Polska
Zarejestrowany: 2007-12-22
Serwis

Re: [SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

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:

Kod:

#!/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

 

#9  2010-03-10 13:31:54

  Jacekalex - Podobno człowiek...;)

Jacekalex
Podobno człowiek...;)
Skąd: /dev/random
Zarejestrowany: 2008-01-07

Re: [SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

Dzięki, ale ze znakiem nowego wiersza poradziłem sobie samodzielnie, chwile po napisaniu tego pytania.
Wystarzyło go wstawić w takiej formie:

Kod:

($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)


W demokracji każdy naród ma taką władzę, na jaką zasługuje ;)
Si vis pacem  para bellum  ;)       |       Pozdrawiam :)

Offline

 

#10  2010-03-10 14:03:14

  Minio - Użyszkodnik

Minio
Użyszkodnik
Skąd: Poznań, Polska
Zarejestrowany: 2007-12-22
Serwis

Re: [SOLVED][PERL]Wyrażenia regularne -kilka pytań [HURRRRAAAAA!!!!!!!!].

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

 

Stopka forum

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson
Nas ludzie lubią po prostu, a nie klikając w przyciski ;-)