2009-10-02 14 views
6

Devo convertire i commenti a riga singola (//...) per bloccare i commenti (/*...*/). Ho quasi compiuto questo nel seguente codice; tuttavia, ho bisogno che la funzione salti ogni singolo commento di linea sia già in un commento di blocco. Attualmente corrisponde a qualsiasi commento a riga singola, anche quando il commento a riga singola è in un commento a blocco.Converti commenti a riga singola per bloccare commenti

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

risposta

1

si potrebbe provare un aspetto negativo dietro: 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 
); 
} 

però mi preoccupa possibili stringhe con // in loro. come: $ x = "una stringa // con barre"; Verrebbe convertito.

Se il file sorgente è PHP, è possibile utilizzare tokenizer per analizzare il file con maggiore precisione.

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

Edit: dimenticato circa la lunghezza fissa, che si può superare con l'annidamento l'espressione. Quanto sopra dovrebbe funzionare ora. L'ho provato 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

Beh, non mi preoccupo se $ x = "qualche stringa // con barre"; diventa $ x = "qualche stringa/* con barre * /" ;. Questo sarebbe in realtà preferito. D'altra parte, ho aggiunto le modifiche che hai suggerito e ottenuto un errore di compilazione. Avviso: preg_replace_callback() [function.preg-replace-callback]: Compilazione non riuscita: l'asserzione lookbehind non è una lunghezza fissa all'offset 6 in C: \ wamp \ www \ LessCSS \ Site \ cleaner \ inc \ util.php on line 29 – roydukkey

+1

Il look-behind di PHP supporta solo asserzioni di lunghezza fissa. Ciò significa che non puoi scrivere un'espressione regolare che corrisponda a un numero indefinito di caratteri, il che esclude l'uso di * e?. Maggiori informazioni qui: http://www.php.net/manual/en/regexp.reference.assertions.php –

+0

grazie per l'heads up. dovrebbe funzionare ora –

3

Come già accennato, "//..." può verificarsi all'interno Blocca i commenti e le stringhe letterali. Quindi, se crei un piccolo "parser" con l'aiuto di un po 'di regex-trickery, puoi prima abbinare una di queste cose (stringhe letterali o block-comments), e dopo verifica se è presente "//...".

Ecco una piccola 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"; 
    } 
} 

che produce il seguente output:

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 

Naturalmente, ci sono più stringhe letterali possibili in PHP, ma si ottiene la mia direzione, presumo.

HTH.