[sed] strippen van html tags maar niet allemaal

Pagina: 1
Acties:

  • lazydave-II
  • Registratie: September 2005
  • Laatst online: 09-01 18:00
Ben al een tijdje bezig om een stuk (oude) html code te rippen met sed om het uiteindelijk in een db te stoppen... Het is bijna gelukt... maar ik zie toch liever een nettere oplossing

output van `cat code.txt`

<font color=white> </font><font color=aqua>Drink bier <a href="bier.html"></font><font color=yellow>128</a></font>

de bedoeling is dat ik deze uitkomst krijg:

Drink bier; bier.html; 128;

(spaties voor of na de ; maken niet uit)


ik doe het no zo maar het kan vast veel handiger:

cat code.txt | sed 's/<font[^>]*>//g' | sed 's/<\/font[^>]*>/;/g' | sed 's/<a href="/;/g' | sed 's/"[^a]*>/ /g' | sed 's/<[^>]*>//g'

output:

;bier. ;bier.html ;128;
;wijn ;wijn.html ;112;
;koffie ;koffie.html ;111;

etc...

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 29-10 06:07

Sprite_tm

Semi-Chinees

Non-greedyness zou hierbij zoooo handig zijn, maar dit werkt iig ook wel:
code:
1
sed -r 's/([^<]*<[^>]*>){3}([^<]*)[^"]*"([^"]*)"([^<]*<[^>]*>){2}([^<]*)<.*$/\2;\3;\5;/'

Ik skip hierbij eerst 3 html-tags, pak de tekst die dan staat, skip alles tot de ", pak de tekst tot de volgende ", skip daarna 2 html-tags (plus evt crap ervoor) en pak de text die daar staat, tot de volgende openingshaak van een html-tag.

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


  • lazydave-II
  • Registratie: September 2005
  • Laatst online: 09-01 18:00
OMG,

al was ik een jaar blijven door puzzelen, hier was ik nooit opgekomen... dit moet wel een van de belachelijkste regels code zijn die ik ooit in mijn source heb geplakt :-)


Thx

over greedyness zijn we het eens... daarom vroeg ik me af is sed wel de juiste tool hiervoor... oftwel wat is een alternatief?

  • u_nix_we_all
  • Registratie: Augustus 2002
  • Niet online
Ik heb in het verleden wel een html2text gebruikt, vervolgens is de text een stuk makkelijker te parsen. YMMV .... ;)

You don't need a parachute to go skydiving. You need a parachute to go skydiving twice.


  • lazydave-II
  • Registratie: September 2005
  • Laatst online: 09-01 18:00
u_nix_we_all schreef op vrijdag 04 december 2009 @ 15:49:
Ik heb in het verleden wel een html2text gebruikt, vervolgens is de text een stuk makkelijker te parsen. YMMV .... ;)
Daar was ik inderdaad mee begonnen... helaas raak ik dan de value kwijt in de href tag

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 29-10 06:07

Sprite_tm

Semi-Chinees

lazydave-II schreef op vrijdag 04 december 2009 @ 15:46:
OMG,

al was ik een jaar blijven door puzzelen, hier was ik nooit opgekomen... dit moet wel een van de belachelijkste regels code zijn die ik ooit in mijn source heb geplakt :-)


Thx

over greedyness zijn we het eens... daarom vroeg ik me af is sed wel de juiste tool hiervoor... oftwel wat is een alternatief?
Daar ben ik dus omheen gaan werken, en dat maakt de regexp zo complex.

Wat ik feitelijk gedaan heb is: Stel, je hebt de regel :1:2:3:
Als je '1' wilt hebben zou je met non-greedyness kunnen matchen op
code:
1
:(.*):

De greedyness zorgt er echter voor dat je '1:2:3' krijgt. Dat wil je echter niet en dus moet je expliciet vertellen dat je die alles tot de eerstkomende dubbelepunt wilt hebben; dus je wil alle karakters vangen behalve de dubbelepunt die je velt afsluit. Dat doe je door een karakterclass te definieren van alle karakters behalve de dubbelepunt: [^:] . Dan kom je uiteindelijk uit op iets als
code:
1
:([^:]*):


Die aanpak van .*x naar [^x]*x maakt dat de regexp heel complex lijkt.

Kan je 'm nu wel grokken?

[ Voor 13% gewijzigd door Sprite_tm op 04-12-2009 17:24 ]

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


Verwijderd

Misschien is dit makkelijker... iig om te lezen :)

code:
1
awk -F'[<>"]' '{OFS = ";"; print $7, $9, $15}' code.txt


oftewel:
- Splits elke regel op kleiner-dan/groter-dan en aanhalingstekens
- Zet output-fieldseparator op puntkomma
- Print veldjes 7, 9 en 15, deze bevatten de gewenste tekst


Overigens kan je met sed wel met non-greedy patterns werken; dan moet je -r als parameter meegeven aan sed, dan gebruikt ie de extended regexps.
Om het voorbeeld van hierboven (:1:2:3:) erbij te halen: /:(.*?):/ pakt de kortst mogelijke match, dus :1: ipv :1:2:3:

  • ajvdvegt
  • Registratie: Maart 2000
  • Laatst online: 29-11 15:31
Ulysses, jouw awk-code lijkt me ook het duidelijkste, maar non-greedy sed lijkt me erg handig! Waarom geeft
code:
1
cat code.txt| sed -r 's~<.*?>~~g'
alleen een lege regel en niet 'Drink bier' als uitvoer (met GNU sed 4.2.1 op Ubuntu 9.10)? non-greedy lijkt niet te werken...

[ Voor 6% gewijzigd door ajvdvegt op 08-12-2009 22:48 ]

I don't kill flies, but I like to mess with their minds. I hold them above globes. They freak out and yell "Whooa, I'm *way* too high." -- Bruce Baum


Verwijderd

Ik krijg pijn in mijn ogen als ik dit zie. Als je dit soort dingen wilt doen, dan is sed niet de juiste tool. Je wilt gewoon een fatsoenlijke parser schrijven voor dit soort dingen. (In Haskell bijvoorbeeld. )

  • ajvdvegt
  • Registratie: Maart 2000
  • Laatst online: 29-11 15:31
@gang-ster: Als je deze code vaker wilt gebruiken zou ik een bestaande HTML parser gebruiken, en de DOM gebruiken (ik zou 't ff in Java doen, maar het is maar net waar je beter in thuis bent). Maar voor een eenmalige conversie lijkt zelfs dat me veel te veel werk, laat staan zelf je parser schrijven. Dan is een scriptje prima op z'n plek m.i.

I don't kill flies, but I like to mess with their minds. I hold them above globes. They freak out and yell "Whooa, I'm *way* too high." -- Bruce Baum


Verwijderd

ajvdvegt schreef op dinsdag 08 december 2009 @ 22:38:
Ulysses, jouw awk-code lijkt me ook het duidelijkste, maar non-greedy sed lijkt me erg handig! Waarom geeft
code:
1
cat code.txt| sed -r 's~<.*?>~~g'
alleen een lege regel en niet 'Drink bier' als uitvoer (met GNU sed 4.2.1 op Ubuntu 9.10)? non-greedy lijkt niet te werken...
Non-greedy werkt helaas toch niet in sed: http://www.gnu.org/software/sed/manual/html_node/Extended-regexps.html#Extended-regexps

Met Perl:
code:
1
perl -pe 's/<.*?>//g' code.txt

of Ruby:
code:
1
ruby -pe 'gsub /<.*?>/, ""' code.txt

lukt het wel:
code:
1
 Drink bier 128
Pagina: 1