request_url_withoutHTTP=,canonical_url_withHTTP=,canonical_url_withoutHTTP=,request_url_withoutHTTP_realspaces=. Reguläre Ausdrücke (Seite 1 von 1) « Tags « Blog « Bernhard Häussner
Bernhard Häussner
Tags: Artikel mit dem Tag «Reguläre Ausdrücke» durchstöbern

Fix subverison error: Valid UTF-8 data followed by invalid UTF-8 sequence

23.06.2010, 16:53

This is a solution to fix problems with SVN when you can't update your working copy for some rather odd reason. Everything you get is an obscure error message like this:

svn: Valid UTF-8 data
(hex: 65 64 69 74 65 64)
followed by invalid UTF-8 sequence
(hex: ad 6c 69 73)

This does not only appear when doing svn update but even pops up while svn status.

Since Subverion can handle binary files this is quite confusing. At luck, after some googling I found out that these errors are caused by file names with e.g. Chinese characters.

Unfortunately the error message can't display the corrupt file name because it contains non-UTF-8 data. So I figured that the „Valid UTF-8 data“ (In this case the hex sequence 0x65, 0x64, 0x69, 0x74, 0x65, 0x64) translates to the string „edited“ using some UTF-8 table.

Since there were way too many files with this string I had to look for the 0xAD 0x6C sequence. This could be the asian symbol 구, but you can't grep for this, because it is not UTF-8 encoded. However we can look for the byte sequence using some perl magic:

find /path/to/workingcopy | perl -n -e "print if /\xAD\x6C/" | less

Note the hex-regexp used here to scan binary content in file names. It outputs a nice (and in this case rather short) list like:

/path/to/workingcopy/folder/of/colleque/edited<AD>list.txt

Interestingly, less tries to expose the binary data. Now you just have to rename the file and you're good to go and able to update your working copy again.

Kommentare: 1 Einträge

Javascript Regular Expressions Beispiele

03.11.2009, 18:18

Viele Javascript-Tutorials zum RegExp-Objekt benutzen die RegExp.$1-Notation und andere unschöne Dinge. Außerdem gibt es mehrere nahezu äquivalente Funktionen, was Reguläre Ausdrücke angeht. Darum habe ich ein Bisschen herumgespielt mit den Funktionen S.match(R), R.exec(S), R.test(S), S.split(R), S.replace(R) und S.search(R). Hier ist die kleine Referenz mit viel Beispiel, mit der ich hoffe arbeiten zu können:

RegExp-Objekte erstellen

// short constructor
var regexp=/a(b?c)/i

// long constructor
var regexp=new RegExp("a(b?c)","i"):
// -> allows runtime configuration
var char="a";
var regexp=new RegExp(char+"(b?c)",'i');

In der Praxis wird man fast immer den kurzen Konstruktor verwenden. Manchmal lässt sich ein dynamisches Erstellen des RegExps vermeiden, indem man den Treffer überprüft.

Finden mit String.match(RegExp) und RegExp.exec(String)

// match: basic usage
"a".match(regexp);   //  null
"abc".match(regexp); // ["abc", "bc"]
// -> "i"-flag: caseinsensitive
"Ac".match(regexp));  // ["Ac", "c"]
"acb".match(regexp); // ["ac", "c"]

// exec: same but method of regexp
regexp.exec("a");   //  null
regexp.exec("abc"); // ["abc", "bc"]
regexp.exec("Ac");  // ["Ac", "c"]
regexp.exec("acb"); // ["ac", "c"]

Bis auf wenige Ausnahmen (siehe unten) sind die beiden Funktionen gleich. Zurückgegeben wird ein Array mit dem gesamten passenden Teil und den im regulären Ausdruck eingeklammerten Teilen.

Prüfen mit RegExp.test(String)

// test: just booleans
/^abc$/.test("abc"); // true
/^abc$/i.test("AbC"); // true
/^abc$/.test("abcd"); // false

Diese Funktion ist zum Validieren von Eingaben recht praktisch, wenn es nicht auf den Inhalt des Strings ankommt.

Teilen mit String.split(RegExp)

// split: arrayify stings
"a,b,c.d".split(/\.|,/) // ["a", "b", "c", "d"]
"a,.b- c .d_e".split(/[.,-_]/) // ["a", "", "b", " c ", "d", "e"]
"a,.b- c .d_e".split(/[.,-_\s]*/) // ["a", "b", "c", "d", "e"]

Das Teilen kann auch mit einem normalen String geschehen, aber mit einem RegExp lassen sich, wie in diesem Beispiel demonstriert erweitere Funktionen implementieren, wie mehrere mögliche Trennzeichen oder das kürzen von Whitespace und leeren Elementen.

Lokalisieren mit String.search(RegExp) und RegExpResult.index

// search: match position
"0123b56b".search(/b/g); // 4
"0123b56b".search(/x/g); // -1

// index: match position, too
/b/.exec("0123b56").index; // 4
"0123b56".match(/b/).index; // 4
// -> "g"-flag:global
/b/g.exec("0123b56b").index; // 4
"0123b56b".match(/b/g).index; // undefined

Interessant ist, dass match und global sich nicht vertragen. Irgenwie ist es schon eine rechte Eigenart dass sich gobale und nicht-globale Ausdrücke so startk unterscheiden, daher würde ich RegExp-Objekte nicht zu weit durch Methodenaufrufe schicken.

Ersetzen mit String.replace(RegExp,replacement)

// replace
var string="ab-ghi-abc-hl-ac"
string.match(regexp); // ["abc", "bc"]
string.replace(regexp,"#")); // "ab-ghi-#-hl-ac"

Globales Finden und Ersetzen

// more global
var regexp2=new RegExp(regexp.source,'g')
string.replace(regexp2,"#"); // "ab-ghi-#-hl-#"
string.match(regexp2); // ["abc", "ac"]
// loop like that:
regexp2.exec(string); // ["abc", "bc"]
regexp2.exec(string); // ["ac", "c"]]
regexp2.exec(string); // null
regexp2.exec(string); // ["abc", "bc"]

Hier unterscheiden sich match() und exec()! Während match() ein Array der allen Treffern aus den kompletten Trefferstellen liefert, liefert exec(), wie beim nicht-globalen, pro Fundstelle je ein Array inclusive Klammerstellen. Um mit exec() alle Treffer zu erhalten, kann man z.B. eine while-Schleife verwenden.

Backreferences

// backreferences
/([ab])c\1/.test("aca"); // true
/([ab])c\1/.test("bcb"); // true
/([ab])c\1/.test("bca"); // false

// replacement backreference
// notice 1-9 limitation
"ll mm kk kx a Bb lL".replace(/([lkb])\1/gi,"$12")
"l2 mm k2 kx a B2 l2"
// beyond 1-9
"abcdefghijklmnopqrst".replace(/(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)/i,"$13-$1-$13+++") // "m-a-m+++qrst"
"abcdefghijklmnopqrst".replace(/(.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(?:.)(.)(?:.)(?:.)(?:.)/i,"$2-$1-$13+++") // "m-a-a3+++qrst"
// get a $
"ab".replace(/(.)/,"$$1") // $1b
"ab".replace(/(.)/g,"$$1") // $1$1
// special backrefs:
"abcdefg".replace(/(d)e/,"[ $`-$1-$' (inst $&) ]") // "abc[ abc-d-fg (inst de) ]fg"

Richtig interessante Dinge lassen sich machen mit Backreferences. Grundsätzlich können doppelte Vorkommen von passenden Teilen geprüft werden. Beim Ersetzen sind sie essenziell für Umformatierungen.

Spezialitäten

// special firefox shortcut:
/a/("cba") // a
/a(.)/("acbab") // ["ac", "c"]
// Ein Bonbon:
/\\/("\\")//["\"]
// Noch eines:
function _(é) {var ì=Array,í=RegExp,è=["join","length","replace"],î=[],_
="\x31",_=_*_,ë=_+_+_*_;for (var i=ë;i>=_;i--) {î[î[è[_]]]=("((\\\x64)"+
(new ì(i)[è[_-_]]("\\"+(ë-i+_)*(_+_)))+")");}var î=new í(î[è[_-_]]("|"),
"\x67"),ï=function(){var I=arguments;for(var i=ë;i>=_;i--){var j=(_+_)*(
ë+_-i);if(I[j]) {return i+I[j];}}},ì="",í=_+ì;for (i=_-_;i<é;i++) {ì+=(i
+"\x20"+í+"\n");í=í[è[_+_]](î,ï);}return ì;}alert(_(9));

Der Firefox-Shortcut könnte zwar praktisch sein, wird aber nicht von vielen Browsern unterstützt, und ist auch ein bisschen zu abstrakt.

Letztere Funktion benutzt Backreferences sowohl im RegExp als auch im Ersetzungstext, zudem ersetzt sie Rekursiv und baut das RegExp dynamisch. Außerdem habe ich sie ein bisschen verschlüsselt, da die Berechnung der ausgegebenen Zahlenreihe eigentlich ein Rätsel ist. Wenn man allerdings weiß, dass ich RegExp verwende, fällt die Lösung leichter, und wenn man es gelöst hat, weiß man vielleicht auch warum es ein perfekter Vorwand ist, um sich etwas mit Regulären Ausdrücken zu beschäftigen.

Such-Wiki zu „javascript regexp“

Kommentare: 2 Einträge

Howto: Alleinstehende Unds für XHTML umwandeln

16.04.2009, 13:22
$text=preg_replace ('/&(?!amp;|quot;|nbsp;|gt;|lt;|laquo;|raquo;|copy;|reg;|#[0-9]{1,5};|#x[0-9A-F]{1,4};)/','&', $text);

In meinem Markup-Parser für diesen Blog hatte ich das Problem, dass ich zwar einzelne & in &amp; umwandeln konnte, damit ich Et-Zeichen im ganz normalen Text schreiben kann, auf der anderen Seite aber auch HTML <tags> erlauben will. Wenn ich jetzt aber über HTML schrieben will, muss ich ja auch irgendwie die größer und kleiner-Zeichen encodieren, damit nicht alles einfach vom Browser gerendert wird. Wenn ich aber ein &lt; eingebe, würde das Kaufmanns-Und sofort zu &amp; umgewandelt und so würde dann im Quelltext &amp;lt; stehen und im Text nicht < sondern &lt;. Also brauchte ich eine Methode um nur einzelne kaufmännische Unds zu finden. Das lief dann auf obigen Regulären Ausdruck hinaus.

Er ersetzt & mit &amp; nur dann, wenn dahinter keines der HTML-Entities folgt. Da es eine sehr lange Liste von benannten HTML-Entities gibt, habe ich nur die aufgenommen, die man in HTML Umwandeln muss („htmlspecialchars“), damit ihre Bedeutung erhalten bleibt und ein paar Sonderzeichen, die ich sonst nie finde. Alles andere (z.B. &eacute; für é, 文字, ...) wird ja von UTF-8 abgedeckt. Für ASCII kann man auch noch die dezimale oder hexadecimale Unicode-Notierung verwenden.

Der regexp verwendet eine Erweiterung, die Negative Vorausschau (?!x). Das ist so etwas wie ein Unter-Ausdruck, der zwischendurch überprüft wird am Text nach der aktuellen Position. Die Buchstaben, die auf den überprüften Ausdrück passen, werden nicht mit "gefressen", sie werden also nicht übersprungen, sondern nur kurz getestet. Nur wenn der Ausdruck nicht zutrifft wird von der Ursprungsposition weiter getestet. Es gibt natürlich auch noch positive Vorausschau (?=x) (die weiter laufen lässt, wenn der Ausdruck passt), sowie positive (?<=x) und negative (?<!x) Zurückschau (die jeweils den Text vor der aktuellen Position prüfen).

Das würde zum Beispiel alle Minuskeln ausgeben, die nach einem „o“ stehen: [a-z](?<=o.). Man beachte den Punkt nach dem „o“. Er steht für das gerade überlaufene Zeichen für das jetzt geprüft wird was (von der aktuellen Position hinter dem Zeichen aus gesehen) davor steht. Das bedeutet in der Rücksicht sieht sich das Zeichen nochmal selbst. Noch ein Beispiel: .(?<=o(?#comment).{5}) findet alle Zeichen 5 Positionen vor „o“.

Diese Features stehen in Ruby übrigens nur teilweise zur Verfügung.

Kommentare: keine
[ Seite 1 ]
 
Χρόνογραφ
© 2008-2017 by Bernhard Häussner - Impressum - Login
Kurz-Link zur Homepage: http://1.co.de/