2009-10-02 15 views
6

Muszę przekonwertować komentarze pojedynczej linii (//...), aby zablokować komentarze (/*...*/). Osiągnąłem to prawie w poniższym kodzie; jednak potrzebuję funkcji do pominięcia dowolnego komentarza pojedynczego wiersza, który już znajduje się w komentarzu bloku. Obecnie pasuje do dowolnego komentarza pojedynczego wiersza, nawet jeśli komentarz pojedynczego wiersza znajduje się w komentarzu blokowym.Konwersja pojedynczej linii Komentarze do blokowania komentarzy

## Convert Single Line Comment to Block Comments 
function singleLineComments(&$output) { 
    $output = preg_replace_callback('#//(.*)#m', 
    create_function(
    '$match', 
    'return "/* " . trim(mb_substr($match[1], 0)) . " */";' 
    ), $output 
); 
} 

Odpowiedz

1

można spróbować negatywne spojrzenie za: http://www.regular-expressions.info/lookaround.html

## Convert Single Line Comment to Block Comments 
function sinlgeLineComments(&$output) { 
    $output = preg_replace_callback('#^((?:(?!/\*).)*?)//(.*)#m', 
    create_function(
    '$match', 
    'return "/* " . trim(mb_substr($match[1], 0)) . " */";' 
), $output 
); 
} 

jednak martwię się o możliwych ciągów z // w nich. na przykład: $ x = "jakiś ciąg // z ukośnikami"; Zostanie przekonwertowany.

Jeśli twoim plikiem źródłowym jest PHP, możesz użyć tokenizera, aby parsować plik z większą dokładnością.

http://php.net/manual/en/tokenizer.examples.php

Edit: Zapomniałeś o stałej długości, który można przezwyciężyć poprzez zagnieżdżanie ekspresji. Powyższe powinno zadziałać teraz. Testowałem go z:

$foo = "// this is foo"; 
sinlgeLineComments($foo); 
echo $foo . "\n"; 

$foo2 = "/* something // this is foo2 */"; 
sinlgeLineComments($foo2); 
echo $foo2 . "\n"; 

$foo3 = "the quick brown fox"; 
sinlgeLineComments($foo3); 
echo $foo3. "\n";; 
+0

Nie martwię się, jeśli $ x = "string // z ukośnikami"; staje się $ x = "jakiś ciąg/* z ukośnikami * /" ;. To byłoby naprawdę korzystne. Z drugiej strony dodałem zmiany, które zasugerowałeś i otrzymałeś błąd kompilacji. Uwaga: preg_replace_callback() [function.preg zastępowania-zwrotna] Opracowanie nieudane: lookbehind twierdzenie nie jest stała długość przy przesunięciu 6 C: \ wamp \ WWW \ LessCSS \ \ strony czyszczenia \ Inc \ util.php online 29 – roydukkey

+1

Funkcja sprawdzania przez PHP obsługuje tylko asercje o stałej długości. Oznacza to, że nie można napisać wyrażeń regularnych dopasowanych do niezdefiniowanej liczby znaków, które wykluczają użycie * i?. Więcej informacji tutaj: http://www.php.net/manual/en/regexp.reference.assertions.php –

+0

dzięki za głowy do góry. powinien teraz działać. –

3

Jak już wspomniano, „//...” może występować wewnątrz komentarzy blokowych i napisowych. Więc jeśli utworzysz mały "analizator składni" z pomocą f trochę regex-trickery, możesz najpierw dopasować jedną z tych rzeczy (napisy łańcuchowe lub komentarze blokowe), a następnie sprawdzić czy "//..." jest obecny.

Oto mały demo:

$code ='A 
B 
// okay! 
/* 
C 
D 
// ignore me E F G 
H 
*/ 
I 
// yes! 
K 
L = "foo // bar // string"; 
done // one more!'; 

$regex = '@ 
    ("(?:\\.|[^\r\n\\"])*+") # group 1: matches double quoted string literals 
    | 
    (/\*[\s\S]*?\*/)   # group 2: matches multi-line comment blocks 
    | 
    (//[^\r\n]*+)    # group 3: matches single line comments 
@x'; 

preg_match_all($regex, $code, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); 

foreach($matches as $m) { 
    if(isset($m[3])) { 
    echo "replace the string '{$m[3][0]}' starting at offset: {$m[3][1]}\n"; 
    } 
} 

która produkuje następujące dane wyjściowe:

replace the string '// okay!' starting at offset: 6 
replace the string '// yes!' starting at offset: 56 
replace the string '// one more!' starting at offset: 102 

Oczywiście, istnieje więcej literały łańcuchowe możliwe w PHP, ale co mi chodzi, jak sądzę.

HTH.

Powiązane problemy