Regexp na HTML'a

Mam sobie kod html i muszę go obrobić (idealnie 1 regexpem) tak żeby uzyskać coś takiego: https://gist.github.com/725276

Muszę po prostu zamienić każdą wartość id i class na wartość_1

Propozycje działające w 1.8.6 bardzo mile widziane (jeśli to możliwe).

a mozesz pokazac przyklad na ktorym jest html i oczekiwany wynik?:slight_smile:

ze swojej strony powiem tylko, ze parsowanie html’a regexami nie jest najlepszym pomyslem, moze jednak hpricot?

Parser to dobry pomysł, tyle, że muszę podobny zabieg zrobić na fragmencie css i do tego użyłem regexp’ów - wieć pomyślałem, że do html’a też użyję regexpów.

W sumie jest:

http://code.google.com/p/ruby-css-parser/

Więc mógłbym spróbować (ale jak zwykle nie mam na to czasu).

squil w międzyczasie podesłała coś takiego (zmodyfikowałem nieco aby działało tylko na atrybutach id|class a nie dowolnych:

body.gsub(/(class|id)="([^\"\']+)"/) {|s| "#{$1}=\"#{$2.split(' ').map{|single| single + "_#{self.number}"}.join(' ')}\""}

mnóstwo niewinnych kotków ginie przy każdym uruchomieniu tego kodu.

Tomash, to w takim razie można to samo powiedzieć o każdym regexpie, który jest czymś bardziej skomplikowanym niż /.*/. Dla mnie sprawa jest prosta. Jeśli zagmwatwany fragment kodu jest konkretnym, wydzielonym kawałkiem (dajmy na to ubrany w metodę), okraszony komentarzem, która wyjaśnia co jest na wejściu, a co na wyjściu + ew. testy to nie widzę problemu. Jeśli przyjdzie na to czas/chęci/potrzeba zawsze mogę go przepisać. Wbrew pozorom nie jest ten kod jakiś skomplikowany (trzeba czytać oczywiście partiami, a nie jako całość).

Tak, wiem, że suchar: http://xkcd.com/208/

Bajizas. Hosiowiak NIGDY nie parsuje się htmla regexpami NIGDY. Po to jest nokogiri. Tak wiem że jest dużo regexpów które pozwolą na tym konkretnym kodzie ale za chwilę się z ziaziają. Dawanie zadań w których celem jest znalezienei regexpa do HTMLa jest świadectwem niekompetencji dającego zadanie.

Dla łatwego i barwnego wytłuamczenia: http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags - 1 odpowiedź.

Dla bardziej ciekawych: http://www.google.com/search?hl=pl&q=why+you+cannot+parse+html+with+regex

@Świstuk: Ale ja nie dałem “zadania” tylko zadałaełm pytanie. Z reguły każdy kto zadaje pytanie nie jest w danym momencie “kompetenty” - to dział “Potrzebna pomoc” a nie “Ociekasz zajebistością ? Pokaż swoje mojo.” Tak czy inaczej dzieĸi za podpowiedzi odnośnie parsera, ten regexp póki co działa na moim html’u, może się nie ziaziaje, jak znajdę chwilę to zamienię na parser i wszyscy będą zadowoleni.

“Create a regular expression ® in Ruby to achieve the following”. Jak dla mnie to brzmi wybitnie jak zadanie. Dlatego nazwałem to zadaniem. Proszę się nie czepiać doboru słów tylko treści ewentualnie.
Puenta była jedna: o ile poszczególne regexpy będą działać na pewnym ograniczonym podzbiorze HTML o tyle nie jesteś w stanie napisać regexpa działającego na wszystkie(w szczególości bardzo bardzo ciężkie jest sprawdzenie czy dany fragment nie jest w CDATA albo komentarzu) , dlatego trzeba się zaopatrzyć w nokogiri.

[quote=Świstak]“Create a regular expression ® in Ruby to achieve the following”. Jak dla mnie to brzmi wybitnie jak zadanie. Dlatego nazwałem to zadaniem. Proszę się nie czepiać doboru słów tylko treści ewentualnie.
Puenta była jedna: o ile poszczególne regexpy będą działać na pewnym ograniczonym podzbiorze HTML o tyle nie jesteś w stanie napisać regexpa działającego na wszystkie(w szczególości bardzo bardzo ciężkie jest sprawdzenie czy dany fragment nie jest w CDATA albo komentarzu) , dlatego trzeba się zaopatrzyć w nokogiri.[/quote]
Nie wiem czy w ogóle przeczytałeś ten problem, czy od razu bez myślenia Ci się włączył tryb: “HTML + regexp? fuuuuuu! Killll!”, ale zauważ, że tam mają być znalezione tylko pewne specyficzne części HTMLa (id="…", class="…"), a tutaj już regexpy bez problemu dadzą radę.

@drogus: To przeczytaj jeszcze raz puentę.
Nie jesteś w stanie sprawdzić czy atrybut nie jest w komentarzu na przykład przy użyciu Regexpa. nie wspominajac o tonie znaków escapujących które mogą być użyte. Więc generalnie regexpom używanym do parsowania HTMLa mówimy NIE.
Szczególnie że jak dla mnie Nokogiri::HTML(tu_html).search(’#tu.na.przykład.selektor.css’).map(&:attributes) jest o tonę prostszy i bardziej czytelny niż regexp potrzebny do tego samego zadania.

[quote]Some people, when confronted with a problem, think
“I know, I’ll use regular expressions.” Now they have two problems.[/quote]
Co ciekawe, nikt nie zadał podstawowego pytania:
Hosiawak - ten HTML, który obrabiasz jest z zewnątrznego źródła, czy sam go generujesz?

[quote=Świstak]@drogus: To przeczytaj jeszcze raz puentę.
Nie jesteś w stanie sprawdzić czy atrybut nie jest w komentarzu na przykład przy użyciu Regexpa. nie wspominajac o tonie znaków escapujących które mogą być użyte. Więc generalnie regexpom używanym do parsowania HTMLa mówimy NIE.
Szczególnie że jak dla mnie Nokogiri::HTML(tu_html).search(’#tu.na.przykład.selektor.css’).map(&:attributes) jest o tonę prostszy i bardziej czytelny niż regexp potrzebny do tego samego zadania.[/quote]
Zdaję sobie z tego sprawę, np. poniższy kod html zostanie zmieniony przez tego regexpa w miejscu gdzie nie powinien być:

<div>We have several documents with id="id" and class="class"</div>

Podsumowanie wątku (dla przyszłych pokoleń :slight_smile: ) : do parsowania HTML’a używamy Nokogiri/Hpricot a nie wyrażeń regularnych.

Świstak: ok, przepraszam, rzeczywiście nie doczytałem, mój błąd :slight_smile:

Już jest wygenerowany i się nie zmienia, dlatego będąc świadomy potencjalnych problemów użyłem tego regexp’a i mogę mimo tego spać spokojnie w nocy :wink:

Jeszcze słówko wyjaśnienia dlaczego muszę zmieniać html’a: Otóż kod html + css jest tak przygotowany, że wyświetla 1 stronę na raz (powiedzmy A4). Jeśli chciałbym sobie wyświetlić 2 strony (z różną zawartością ale używając tego samego html+css) to wstawiam kod html+css dotyczący drugiej strony poniżej tego pierwszego (powiedzmy jakiś div id=wrapper) i w tym momencie mam konflikt id’ków i klas z css (reguły css’a dotyczące tylko jednej strony zostają użyte na wszystkich stronach) - stąd moja próba automatycznego rozdzielenia id/class na poszczególne strony nadając im unikalne nazwy w momencie generowania dokumentu.

To nie ma co rzucać kamieniami za używanie regexp. Śpij spokojnie :wink:

Dobrze że dopiero teraz opisał warunki problemu – co poflejmowaliśmy to nasze :smiley: