2010-01-25 14 views
6

Me gustaría filtrar (principalmente una línea) los comentarios de (en su mayoría válidos) JavaScript utilizando el módulo re de python. Por ejemplo:Coincidencia de comentarios de una línea de JavaScript (//) con re

// this is a comment 
var x = 2 // and this is a comment too 
var url = "http://www.google.com/" // and "this" too 
url += 'but // this is not a comment' // however this one is 
url += 'this "is not a comment' + " and ' neither is this " // only this 

Ahora estoy intentando esto por más de media hora sin ningún éxito. ¿Alguien puede ayudarme por favor?

EDIT 1:

foo = 'http://stackoverflow.com/' // these // are // comments // too // 

EDIT 2:

bar = 'http://no.comments.com/' 
+6

En este punto, debe considerar el uso de un analizador adecuado en lugar de intentar hackear una expresión regular. –

+0

Gracias Anon., Si no puedo encontrar una expresión regular pronto, buscaré un analizador sintáctico. SpiderMonkey tal vez? –

Respuesta

7

Mis poderes de expresión regular habían quedado un poco obsoletos, así que he usado tu pregunta para actualizar lo que recuerdo. Se convirtió en una expresión regular bastante grande sobre todo porque también quería filtrar comentarios de varias líneas.

import re 

reexpr = r""" 
    (       # Capture code 
     "(?:\\.|[^"\\])*"  # String literal 
     | 
     '(?:\\.|[^'\\])*'  # String literal 
     | 
     (?:[^/\n"']|/[^/*\n"'])+ # Any code besides newlines or string literals 
     | 
     \n      # Newline 
    )| 
    (/\* (?:[^*]|\*[^/])* \*/)  # Multi-line comment 
    | 
    (?://(.*)$)     # Comment 
    $""" 
rx = re.compile(reexpr, re.VERBOSE + re.MULTILINE) 

Esta expresión regular coincide con tres subgrupos diferentes. Uno para el código y dos para los contenidos del comentario. A continuación se muestra un ejemplo de cómo extraerlos.

code = r"""// this is a comment 
var x = 2 * 4 // and this is a comment too 
var url = "http://www.google.com/" // and "this" too 
url += 'but // this is not a comment' // however this one is 
url += 'this "is not a comment' + " and ' neither is this " // only this 

bar = 'http://no.comments.com/' // these // are // comments 
bar = 'text // string \' no // more //\\' // comments 
bar = 'http://no.comments.com/' 
bar = /var/ // comment 

/* comment 1 */ 
bar = open() /* comment 2 */ 
bar = open() /* comment 2b */// another comment 
bar = open(/* comment 3 */ file) // another comment 
""" 

parts = rx.findall(code) 
print '*' * 80, '\nCode:\n\n', '\n'.join([x[0] for x in parts if x[0].strip()]) 
print '*' * 80, '\nMulti line comments:\n\n', '\n'.join([x[1] for x in parts if x[1].strip()]) 
print '*' * 80, '\nOne line comments:\n\n', '\n'.join([x[2] for x in parts if x[2].strip()]) 
+0

Vaya, esto es incluso un paso por delante de la pregunta, ¡pero esto es exactamente lo que necesito! ¡Muchas gracias por tomarse su tiempo para resolver este problema! –

+0

He editado la expresión regular porque no coincide con '*' como en 'x = 4 * 5', que se convirtió en 'x = 4 5)' – driax

+1

No funciona para '/ */* /' o '/ * // */'. Solución: reemplace '/ \\ * (?: \\ *? [^ /] | \ N) * \\ * /' con '/ \\ * (?: [^ *] | \\ * [^ /]) * \\ */'. – Gumbo

1

Puede ser que sea más fácil de analizar si tuviera explícitas punto y coma.

En cualquier caso, esto funciona:

import re 

rx = re.compile(r'.*(//(.*))$') 

lines = ["// this is a comment", 
    "var x = 2 // and this is a comment too", 
    """var url = "http://www.google.com/" // and "this" too""", 
    """url += 'but // this is not a comment' // however this one is""", 
    """url += 'this "is not a comment' + " and ' neither is this " // only this""",] 

for line in lines: 
    print rx.match(line).groups() 

salida de los anteriores:

('// this is a comment', ' this is a comment') 
('// and this is a comment too', ' and this is a comment too') 
('// and "this" too', ' and "this" too') 
('// however this one is', ' however this one is') 
('// only this', ' only this') 

no estoy seguro de lo que estás haciendo con el javascript después de eliminando los comentarios, pero JSMin podría ayudar. Elimina los comentarios lo suficientemente bien de todos modos, y hay un implementation in python.

+0

Gracias, definitivamente es un +1. Permítanme modificar mi pregunta un poco ahora :) –

+0

Además, JavaScript no está escrito por mí, así que lamentablemente no puedo garantizar el punto y coma explícito ... –

+3

Ehm, no, esto solo funcionará si siempre hay un comentario en al final de la línea, y cuando no hay // dentro del comentario en sí. Ambos 'var url =" http: // www "' y '// los comentarios se inician con //' fallarán. –

Cuestiones relacionadas