Re: awk/shell-Rätsel

From: Marc Santhoff <M.Santhoff(at)web.de>
Date: Wed, 14 Jan 2009 10:49:29 +0100

Am Mittwoch, den 14.01.2009, 08:36 +0100 schrieb Oliver Fromme:
> Marc Santhoff wrote:
> > #!/bin/sh
> >
> > awk '{ gsub(/</, "\\&lt;"); \
> > gsub(/>/, "\\&gt;"); \
> > gsub(/&/, "\\&amp;"); \
> > gsub(/"/, "\\&quot;"); \
> > gsub(/\'/, "\\&apos;"); \
> > print }' -
>
> Da ist noch ein kleiner Fehler: Das "&" musst Du als
> allererstes konvertieren. Sonst wird nämlich aus einem
> ">" zuerst ein "&gt;" und in der nächsten Zeile sofort
> ein "&amp;gt;", was sicherlich nicht beabsichtigt ist.

Ups, tatsächlich.

> In /bin/sh kann man kann doppelte und einfache Anführungs-
> zeichen wie folgt in sich selbst quoten:
>
> $ echo "foo\"bar"
> "
> $ echo 'foo'\''bar'
> '
>
> Die vorletzte Zeile in Deinem Skript müsste also so aussehen:
>
> gsub(/'\''/, "\\&apos;")

Wunderbar, das funktioniert toll! Danke, auch an Nicolas. :)

$ echo "dies&das" | xmlencode
dies&amp;das

$ echo "'dies&das'" | xmlencode
&apos;dies&amp;das&apos;

> Übrigens, die Semikolons und Backslashes an den Zeilenenden
> sind überflüssig (schaden aber nicht); awk akzeptiert ein
> Newline als Kommandotrenner.
>
> Falls das Shellskript außer dem awk-Kommando nichts weiter
> enthält, dann brauchst Du gar keine /bin/sh, sondern
> kannst es direkt als awk-Skript schreiben, womit Du die
> Quoting-Problematik der Shell ganz vermeidest:
>
> #!/usr/bin/awk -f
> {
> gsub(/&/, "\\&amp;")
> gsub(/</, "\\&lt;")
> gsub(/>/, "\\&gt;")
> gsub(/"/, "\\&quot;")
> gsub(/'/, "\\&apos;")
> print
> }

Stimmt, ich kann aber nicht ausschließen, daß später noch anderes nötig
wird.

> Alternativ kannst Du ein sed-Skript nehmen, das etwa drei-
> bis viermal schneller ist:
>
> #!/usr/bin/sed -f
> s/&/\&amp;/g
> s/</\&lt;/g
> s/>/\&gt;/g
> s/"/\&quot;/g
> s/'/\&apos;/g

Solche Geschichten benutze ich öfter, das werde ich mir jedenfalls
merken.

> Wo ich gerade dabei bin: Eine Lösung in Python ist nochmal
> ein Drittel schneller, allerdings gehört Python nicht zum
> Basissystem von FreeBSD, insofern ist es weniger portabel.
>
> #!/usr/local/bin/python
> from sys import stdin, stdout
> t = stdin.read()
> t = t.replace("&", "&amp;")
> t = t.replace("<", "&lt;")
> t = t.replace(">", "&gt;")
> t = t.replace('"', "&quot;")
> t = t.replace("'", "&apos;")
> stdout.write(t)

Schön, vor allem wo ich gerade begonnen habe, wirklich mal ein Skript in
Python zu schreiben. ;)

> (Den Geschwindigkeitsvergleich habe ich mit einer 25MB-Datei
> gemacht, in der in ca. jeder fünften Zeile eine Ersetzung
> gemacht werden musste.)

Bei mir geht es im Moment gerade nur um Verzeichnisauflistungen, also
eher ein Fall für awk oder sed, da die Datenmenge winzig ist und man
schon (auf meinem Rechner) deutlich merkt, daß Python erst geladen
werden muß. (Wobei ich gerade nichtmal weiß, ob Hochkommata überhaupt in
Dateinamen erlaubt sind.)

Nochmal vielen Dank für die lehrreichen Ausführungen,

-- 
Marc Santhoff <M.Santhoff(at)web.de>
To Unsubscribe: send mail to majordomo(at)de.FreeBSD.org
with "unsubscribe de-bsd-questions" in the body of the message
Received on Wed 14 Jan 2009 - 10:56:49 CET

search this site