regex: \d findet "2" aber nicht "2.957839"

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
michaa7
Beiträge: 4919
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

regex: \d findet "2" aber nicht "2.957839"

Beitrag von michaa7 » 29.01.2014 21:16:08

Der Betreff ist im Grunde die Frage. Warum findet \d nur eine einzelne Ziffer wie "2", und nicht eine längere Dezimalzahl wie "2.957839" (wo "d" doch für decimal digit = Dezimalzahl steht)?

Konkret versuche ich mit Geany ein svg (xml-datei) zu bearbeiten. Dabei suche ich nach dem textstring
"stroke-width:" dem eine beliebige Dezimalzahl folgt. Als Ende der Sequenz dient ein ";". Das ergibt zunächst folgenen Suchstring:
"stroke-width:[\d];" was ich durch "stroke-width:2;" ersetzen will (jeweils ohne "").
Ich habe
"stroke-width:[\d{*}];"
"stroke-width:[\d{?}];"
"stroke-width:[+\d];"
und ein paar mehr Varianten versucht.

EDIT:/
Diese Version findet ganze Zahlen ohne Dezimalen *oder* Zahlen mit 8 Dezimalstellen. Wie kann ich die Anzahl der Dezimalstellen verallgemeinern zu wenigstens 0-8?
stroke-width:[0-9]?[0-9]?(\.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]?)?;
/EDIT:/

Es werden aber keine vorhandenen *mehrziffrigen* Dezimalzahlen gefunden. Möglicherweise steht hier der Dezimalpunkt statt des Dezimalkommas im Weg? Was tun?

Und, BTW, kennt jemand eine brauchbarere Manpage als die in Geany verlinkte GLib Regex man page?
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

Benutzeravatar
TRex
Moderator
Beiträge: 8322
Registriert: 23.11.2006 12:23:54
Wohnort: KA

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von TRex » 29.01.2014 22:10:44

Code: Alles auswählen

\d+\.\d{1,8}
?

Edit:

Code: Alles auswählen

\d+(\.\d{1,8})?
Jesus saves. Buddha does incremental backups.
Windows ist doof, Linux funktioniert nichtDon't break debian!Wie man widerspricht

wanne
Moderator
Beiträge: 7548
Registriert: 24.05.2010 12:39:42

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von wanne » 29.01.2014 22:43:02

Ich glaube digit heißt Ziffer nicht Zahl. Auch wenn dict.cc was anderes sagt.
rot: Moderator wanne spricht, default: User wanne spricht.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von Cae » 29.01.2014 23:12:15

Warum nicht

Code: Alles auswählen

stroke-width:[0-9.]+;
? Nach klassischer RegEx-Syntax hat man da eine Gruppe, die aus Ziffern und Punkten besteht. Wobei auch etwas wie 123.456.7 gematcht werden wuerde.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

michaa7
Beiträge: 4919
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von michaa7 » 29.01.2014 23:37:53

Danke euch allen drei. Sehr hilfreich, Variante 1 (TRex) findet zwar keine Zahlen ohne Nachkommastellen, aber Variante 2 (TRex) tut was sie soll, und Variante 3 (Cae), so kurz sie ist, tut ebenso was ich brauche. Und last but not least, tja "digit" heißt zwar auch Ziffer, aber in den GLib manpage zu regex steht eben:
\d any decimal digit
Heißt dann wohl "/d = jede dezimalzahl", was sollte denn eine Dezimalziffer auch sein? digit ist also missverständlich, aber diese manpage ist wenig hilfreich zum verstehen der regex-*syntax*.
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von Cae » 30.01.2014 00:39:20

Vermutlich ist "decimal digit" einfach ein ueberdeutlicher Ausdruck wie "weisser Schimmel" oder "kaltes Eis". Vielleicht zur Abgrenzung zu "hexadeciamal digits" aka. [0-9a-f]... aber u.U. auch einfach ein Schusselfehler des Autors.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

wanne
Moderator
Beiträge: 7548
Registriert: 24.05.2010 12:39:42

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von wanne » 30.01.2014 00:41:21

michaa7 hat geschrieben:was sollte denn eine Dezimalziffer auch sein?
Dezimalziffer: 0,1,2,3,4,5,6,7,8,9 und nichts sonst.
Im gegensatz dazu Oktalziffer: 0,1,2,3,4,5,6,7 aber kein 8 und 9
rot: Moderator wanne spricht, default: User wanne spricht.

michaa7
Beiträge: 4919
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von michaa7 » 30.01.2014 02:46:09

wanne hat geschrieben:
michaa7 hat geschrieben:was sollte denn eine Dezimalziffer auch sein?
Dezimalziffer: 0,1,2,3,4,5,6,7,8,9 und nichts sonst.
Im gegensatz dazu Oktalziffer: 0,1,2,3,4,5,6,7 aber kein 8 und 9
In der tat, ich wollte es nicht glauben, aber das ist des rätsels lösung:

Table 3. Non-printing charactersEscape Meaning
\a alarm, that is, the BEL character (hex 07)
\cx "control-x", where x is any character
\e escape (hex 1B)
\f formfeed (hex 0C)
\n newline (hex 0A)
\r carriage return (hex 0D)
\t tab (hex 09)
\ddd character with octal code ddd, or backreference
\xhh character with hex code hh
\x{hhh..} character with hex code hhh..
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

Benutzeravatar
hikaru
Moderator
Beiträge: 13909
Registriert: 09.04.2008 12:48:59

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von hikaru » 30.01.2014 09:14:35

Cae hat geschrieben:Warum nicht

Code: Alles auswählen

stroke-width:[0-9.]+;
?
Weil das auch sowas matcht:
.................

uname
Beiträge: 12403
Registriert: 03.06.2008 09:33:02

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von uname » 30.01.2014 09:40:53

Ich habe noch mal deine ursprüngliche Frage gelesen. Von wie vielen Einträgen reden wir und gibt es eine von dir vorgegebenen Algorithmus zur Umwandlung? Wenn ja denke ich, dass Debiangeany gar nicht die richtige Anwendung für dein Problem ist. Ich denke "sed" wäre zielführender.

Also bitte erzähl uns was aus z.B.

Code: Alles auswählen

stroke-width:2.12345678;
werden soll. Im Beispiel wäre es:

Code: Alles auswählen

stroke-width:2;
Soll das immer so sein? Versuche deinen Algorithmus zu beschreiben wie z.B. Kürzung auf ganze Zahlen, Kürzung an Stelle XY, ...

michaa7
Beiträge: 4919
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von michaa7 » 30.01.2014 14:54:16

Es geht nicht darum Zahlen zu runden. Es geht hier darum Konturdicken zu vereinheitlichen. Inkscape selbst und auch der eingebaute XML Editor sind für den Fall von vielen Dateien sehr unhandlich, Geany war dagegen ein wirklicher Glücksgriff. Ich kannte zwar die RegEx Funktion von Geany, nicht aber, dass ich sie auf eine komplette Sitzung (= alle in Geany gerade geöffneten Dateien) anwenden kann. In soweit hat es sich gestern sogar zeitlich gelohnt, mit RegEx zu experimentieren und hier nachzufragen. Als das RegEx dann klar war habe ich in 10 Sekunden erledigt, wofür ich manuell gut zwei Stunden gebraucht hätte, theoretisch, denn bei derart repetitiven Arbeiten steige ich konzentrationsmäßig recht schnell aus.

Vielleicht geht das auch mit sed, nur kommt dann bestimmt der nächste und sagt, probier doch awk, ist für kompliziertere Fälle noch mächtiger als sed. Im Grunde wünschte ich mir, ich hätte Skriptfähigkeiten, weil eigentlich noch mehr automatisierbares der manuellen Bearbeitung harrt.
Falls da jemand ein TUT kennt, welches kleine Brötchen backen hilft (sprich, ich schnell kleine Erfolge damit habe) um zu lernen wie ich per Schleife bestimmte Dateien in einem Ordner nach Mustern durchkämme und diese ändere, wäre ich sehr dankbar.

Es gibt in mehr als 40 SVGs noch mehr zu ändern, was ich wohl wegen der für mich steilen Lernkurve was das Skripten betrifft dann doch manuell in Inkscape ändern werde. Dabei ginge es z.B. darum, die Ausdehnung eines bestimmten Rechtecks auf immer die gleichen neuen Werte zu ändern. Da sed und awk zeilenbasierte Anwendungen sind scheiden sie dazu wohl ehr aus (mal davon abgesehen, dass ich auch da bei nahe null beginnen müsste).
RegEx kann zumindest in Geany auch mehrzeilige Muster suchen. Ob damit ein bestimmtes Rechteck in einer XML Suppe identifiziert und in einzelnen Parametern geändert werden kann kann ich nicht übersehen. Aber weil du gefragt hast, hier eine Beispielaufgabe (die ich auch deshalb hier poste, weil ich derzeit eher geneigt bin meine RegEx Fähigkeiten auszubauen, als x-mal die selben Dialoge in Inkscape aufzurufen, Datei für Datei):
...bli..bla..blub...
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="hg"
style="display:inline"
transform="translate(0,-283.46455)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#7f7f7f;stroke-width:0.53149605;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
id="rect4061"
width="70.317841"
height="70.572021"
x="0.282552"
y="283.49292" />
</g>
<g
inkscape:label="formen"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-981.49472)"
style="display:inline">
<path ...bli..bla..blub...


Wie würde ich nach " <rect <irgendwas> id="rect4061" <irgendwas> />" suchen um nur dort

"
width="70.317841"
height="70.572021"
x="0.282552"
y="283.49292"
"

immer auf bestimmte neue Werte zu ändern.

Wie gesagt, vermutlich muß ich das in Inkscape manuell ändern. Aber wenn jemand die Lernkurve um dies per skript/regex zu erledigen für mich glätten könnte würde ich nicht wegrennen ;-)

EDIT://
Vermutlich wäre es am einfachsten, den ganzen Block auszutauschen:

Alt
<g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="hg"
style="display:inline"
transform="translate(0,141.73231)">
<rect
style="fill:#000000;fill-opacity:1;stroke:#7f7f7f;stroke-width:0.53149605;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect4061"
width="354.896"
height="354.32358"
x="-0.57241285"
y="0.5795297" />
</g>
gegen Neu:
<g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="hg"
style="display:inline"
transform="translate(0,-283.46455)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#7f7f7f;stroke-width:0.53149605;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
id="rect4061"
width="70.317841"
height="70.572021"
x="0.282552"
y="283.49292" />
</g>
Wobei der jeweils gesuchte "<g ... />" Block durch die darin enthaltenen Zeilen "inkscape:label="hg"" und/oder "id="rect4061"" identifizierbar wäre.

Grundsätzlich wäre das zwar gerade noch so manuell machbar (mit spaßfaktor -13). Da aber insgesamt die Zahl der weiter zu bearbeitenden SVGs eher noch steigen wird, und ich eben auch zukünftig damit rechne für *alle* Dateien gültige Änderungen vornehmen zu wollen wäre eine Regex/script infrastruktur zur automatisierbaren Bearbeitung hilfreich. Derzeit habe ich nun (fast) alle SVGs so umgearbeitet, dass über zumindest über die verwendeten layer der jeweils gleich layoutete Inhalt selektierbar wäre. Im einzelfall jedoch nur über den Layer, nicht über eine gleiche ID.
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von Cae » 31.01.2014 00:52:12

hikaru hat geschrieben:
Cae hat geschrieben:Warum nicht

Code: Alles auswählen

stroke-width:[0-9.]+;
?
Weil das auch sowas matcht:
.................
Ja, das war mir bewusst (siehe auch der Nachsatz oben im Post). Ich hielt/halte das aber vertretbar, weil es nicht wirklich um input validation geht, sondern es schon klar ist, dass da nur eine Zahl und ggf. ein Punkt als Dezimaltrennzeichen stehen kann.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
goeb
Beiträge: 348
Registriert: 26.08.2006 18:12:08
Lizenz eigener Beiträge: MIT Lizenz

Re: regex: \d findet "2" aber nicht "2.957839"

Beitrag von goeb » 31.01.2014 02:10:14

Wenn du XML editieren willst nimm ein Tool zum XML editieren, Debianxmlstarlet sollte dir weiterhelfen, z.B.:

Code: Alles auswählen

xmlstarlet edit -N 'N=http://www.w3.org/2000/svg' \
  --update '//N:rect/@width'  --value 1 \
  --update '//N:rect/@height' --value 1 \
  Zeichnung.svg

Antworten