2017-12-07 9 views
0

Ich arbeite derzeit an einer Minification-Aufgabe als Post-Commit-Hook. Ich benutze die aktuelle Version von yui-compressor für CSS-Minification.sed regulären Ausdruck zu beheben css Verkleinerung

Schlechte Sache über die aktuelle Version von yui-Kompressor: Es bricht bestimmte CSS3-Regeln, die Whitespaces brauchen, um richtig zu funktionieren. (calc (10px + 10px))

Um das Problem zu beheben, schrieb ich einen regulären Ausdruck, der jedes Auftreten von calc (...) nach der Komprimierung ersetzen sollte.

meine Lösung so weit ist die folgende RegEx:

Match: /calc\((.*?)([\/\+\-\*])(.*?)\)/g

ersetzen: calc(\1 \2 \3)

ich zwei Online-Tools verwenden meinen regulären Ausdruck zu validieren:

https://regex101.com/

https://regexr.com/

Es funktioniert auch in PHP. Aber sobald ich verwende „sed“ nur das letzte Vorkommen pro Zeile ersetzt wird:

Komprimierte CSS: (vor dem Ersetzen mit regulären Ausdrücken)

.test{width:calc(1px+1px)}.test2{left:calc(4%+140px)}.test3{width:calc(1px+1px)} 

.test{width:calc(1px-1px)}.test2{left:calc(4%-140px)}.test3{width:calc(1px-1px)} 

.test{width:calc(1px*1px)}.test2{left:calc(4%*140px)}.test3{width:calc(1px*1px)} 

.test{width:calc(1px/1px)}.test2{left:calc(4%/140px)}.test3{width:calc(1px/1px)} 

CSS nach regulärem Ausdruck: (und richtigen Ergebnis)

.test{width:calc(1px + 1px)}.test2{left:calc(4% + 140px)}.test3{width:calc(1px + 1px)} 

.test{width:calc(1px - 1px)}.test2{left:calc(4% - 140px)}.test3{width:calc(1px - 1px)} 

.test{width:calc(1px * 1px)}.test2{left:calc(4% * 140px)}.test3{width:calc(1px * 1px)} 

.test{width:calc(1px/1px)}.test2{left:calc(4%/140px)}.test3{width:calc(1px/1px)} 

in debian sed 8 - (Laden die gleichen Regeln aus einer Datei):

sed -r "s/calc\((.*?)([\/\+\-\*])(.*?)\)/calc(\1 \2 \3)/g" style.css 

druckt die folgenden:

.test{width:calc(1px+1px)}.test2{left:calc(4%+140px)}.test3{width:calc(1px + 1px)} 
.test{width:calc(1px-1px)}.test2{left:calc(4%-140px)}.test3{width:calc(1px-1px)} 
.test{width:calc(1px*1px)}.test2{left:calc(4%*140px)}.test3{width:calc(1px * 1px)} 
.test{width:calc(1px/1px)}.test2{left:calc(4%/140px)}.test3{width:calc(1px/1px)} 

Es scheint nicht mit sed zu arbeiten. Hat jemand eine Ahnung, was zum Teufel ist los?

Vielen Dank im Voraus!

Antwort

0

Sie versuchen, PCRE non-gierige Wiederholung .*? zu verwenden, aber sed unterstützt nur POSIX BRE and ERE, die die nicht gierige Erweiterung nicht definieren.

Stattdessen müssen Sie Ihren regulären Ausdruck ändern. In Ihrem Fall könnten Sie [^-+*/]* für die erste erfasste Gruppe verwenden (linker Operand) - um alles bis zum Operator abzugleichen, und [^)]*, um den zweiten Operanden - alles bis zur schließenden Klammer - zu finden. Dies wird produzieren die Ausgabe, die Sie erwarten:

sed -E 's/calc\(([^-+*/]*)([-+*/])([^)]*)\)/calc(\1 \2 \3)/g' style.css 
#    ^^^^^^^^ ^^^^^^ ^^^^^ 
#   left operand op right operand 
#   all until op   all until) 

Notiere die -E--r gleichwertig ist, sondern funktioniert auch in nicht-GNU sed. Außerdem müssen Sie Ihren Operatoren nicht innerhalb der Klammern entkommen. In der Tat muss fast nichts in den Klammern entfernt werden - mit Ausnahme der schließenden Klammer, wenn sie nicht als erstes Zeichen geliefert wird, und ^, wenn sie als erstes Zeichen geliefert wird.

Der Ausgang Sie waren immer ist leicht zu erklären, wenn Sie die .*? beachten als gierig .* behandelt wird, wiederholt null oder mehr Male (?) - Die ersten .*? alles bis zum letzten Operator in Zeile erfaßt, und den zweiten .*? fängt den letzten Operanden ein und "expandiert" daher nur den letzten calc Ausdruck in jeder Zeile.

+0

Funktioniert wie ein Charme. Danke vielmals. Ich war mir nicht bewusst, dass sed so "primitiv" ist. –

+0

Gern geschehen. Tatsächlich kann 'sed' viel mehr tun als ersetzen (' s' Befehl). Es hat Verzweigungs- und Schleifenkonstrukte; ziemlich mächtig, in der Tat. :) Leider wird PCRE nicht unterstützt, aber wenn Sie es brauchen, möchten Sie vielleicht Perl ausprobieren. – randomir