2009-10-02 23 views
6

Necesito convertir comentarios de una sola línea (//...) para bloquear los comentarios (/*...*/). Casi he logrado esto en el siguiente código; sin embargo, necesito que la función para omitir cualquier comentario de una sola línea ya esté en un comentario en bloque. Actualmente coincide con cualquier comentario de una sola línea, incluso cuando el comentario de una sola línea está en un comentario en bloque.Convertir comentarios de una sola línea para bloquear comentarios

## 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 
); 
} 

Respuesta

1

usted podría intentar un aspecto negativo atrás: 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 
); 
} 

sin embargo me preocupe por posibles cadenas con // en ellos. como: $ x = "alguna cadena // con barras"; Se convertiría.

Si su archivo fuente es PHP, puede usar tokenizer para analizar el archivo con mayor precisión.

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

Editar: se olvidó de la longitud fija, que puede superar por los nidos de la expresión. Lo anterior debería funcionar ahora. Lo he comprobado con:

$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

Bueno, no me preocupa si $ x = "alguna cadena // con barras"; se convierte en $ x = "alguna cadena/* con barras inclinadas * /" ;. Eso sería realmente preferido. Por otro lado, agregué los cambios que sugirió y obtuve un error de compilación. Advertencia: preg_replace_callback() [function.preg-replace-callback]: Compilación fallida: la aserción lookbehind no es de longitud fija en el desplazamiento 6 en C: \ wamp \ www \ LessCSS \ Site \ cleaner \ inc \ util.php on line 29 – roydukkey

+1

El look-behind de PHP solo admite aserciones de longitud fija. Eso significa que no se puede escribir una expresión regular que se parezca a un número indefinido de caracteres, lo que excluye el uso de * y?. Más información aquí: http://www.php.net/manual/en/regexp.reference.assertions.php –

+0

gracias por el aviso. debería funcionar ahora. –

3

Como ya se ha mencionado, "//..." puede ocurrir dentro de los comentarios de bloques y literales de cadena. Por lo tanto, si crea un pequeño "analizador" con la ayuda de un poco de artimañas regex, primero podría hacer coincidir cualquiera de esas cosas (literales de cadena o comentarios de bloque), y luego probar si "//..." está presente.

He aquí una pequeña demostración:

$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"; 
    } 
} 

que produce el siguiente resultado:

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 

Por supuesto, hay más cadenas literales posibles en PHP, pero usted me entiende, supongo.

HTH.

Cuestiones relacionadas