2011-10-04 20 views
15

Tengo una gran base de datos que contiene registros que tienen etiquetas <a> en ellas y me gustaría eliminarlas. Por supuesto, existe el método donde creo un script PHP que selecciona todo, usa strip_tags y actualiza la base de datos, pero esto lleva mucho tiempo. Entonces, ¿cómo puedo hacer esto con una simple (o complicada) consulta MySQL?¿Cuál es el equivalente de consulta MySQL de PHP strip_tags?

Respuesta

4

No creo que haya ninguna forma eficiente de hacerlo en MySQL solo.

MySQL tiene una función REPLACE(), pero solo puede reemplazar cadenas constantes, no patrones. Posiblemente podría escribir una función almacenada en MySQL para buscar y reemplazar etiquetas, pero en ese punto probablemente sea mejor que escriba un script PHP para hacer el trabajo. Puede que no sea bastante tan rápido, pero probablemente será más rápido de escribir.

+0

sí, probablemente estás justo :( – faq

-1

REPLACE() funciona bastante bien.

El acercamiento sutil:

REPLACE(REPLACE(node.body,'<p>',''),'</p>','') as `post_content` 

... y el no tan sutil: (conversión de cadenas en las babosas)

LOWER(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(TRIM(node.title), ':', ''), 'é', 'e'), ')', ''), '(', ''), ',', ''), '\\', ''), '\/', ''), '\"', ''), '?', ''), '\'', ''), '&', ''), '!', ''), '.', ''), '–', ''), ' ', '-'), '--', '-'), '--', '-'), '’', '')) as `post_name` 
16

Aquí van:

CREATE FUNCTION `strip_tags`($str text) RETURNS text 
BEGIN 
    DECLARE $start, $end INT DEFAULT 1; 
    LOOP 
     SET $start = LOCATE("<", $str, $start); 
     IF (!$start) THEN RETURN $str; END IF; 
     SET $end = LOCATE(">", $str, $start); 
     IF (!$end) THEN SET $end = $start; END IF; 
     SET $str = INSERT($str, $start, $end - $start + 1, ""); 
    END LOOP; 
END; 

hice Asegúrese de que elimine los corchetes de apertura no coincidentes porque son peligrosos, aunque ignora los corchetes de cierre no emparejados porque son inofensivos.

mysql> select strip_tags('<span>hel<b>lo <a href="world">wo<>rld</a> <<x>again<.'); 
+----------------------------------------------------------------------+ 
| strip_tags('<span>hel<b>lo <a href="world">wo<>rld</a> <<x>again<.') | 
+----------------------------------------------------------------------+ 
| hello world again.             | 
+----------------------------------------------------------------------+ 
1 row in set 
+0

no funcionó para mí; MySQL dijeron: Documentación # 1064 - Usted tiene un error en su sintaxis SQL, consulte el manual que corresponde a su versión del servidor MySQL para la sintaxis correcta al uso cerca '' en la línea 3 – mahen3d

+4

'delimitador // CREATE strip_tags función ($ texto str) Retorna el texto COMENZAR DECLARE $ inicio, final INT DEFAULT $ 1; BUCLE SET $ = inicio LOCALIZAR ("<", $ str, $ start); IF (! $ Start) ENTONCES RETORNO $ str; TERMINARA SI; SET $ end = LOCATE (">", $ str, $ start); IF (! $ End) LUEGO SET $ end = $ start; TERMINARA SI; SET $ str = INSERT ($ str, $ start, $ end - $ start + 1, ""); END LOOP; END // delimitador; ' – nzn

+0

DROP FUNCTION if EXISTS strip_tags; DELIMITER | CREAR FUNCIÓN strip_tags (texto $ str) DEVOLUCIONES texto COMIENZO DECLARAR $ start, $ end INT DEFAULT 1; LOOP SET $ start = LOCATE ("<", $ str, $ start); IF (! $ Start) ENTONCES RETORNO $ str; TERMINARA SI; SET $ end = LOCATE (">", $ str, $ start); IF (! $ End) LUEGO SET $ end = $ start; TERMINARA SI; SET $ str = INSERT ($ str, $ start, $ end - $ start + 1, ""); END LOOP; END; | DELIMITER; – IRvanFauziE

5

Estoy transmitiendo este código, parece muy similar al anterior. Trabajó para mí, espero que ayude.

BEGIN 
    DECLARE iStart, iEnd, iLength INT; 

    WHILE locate('<', Dirty) > 0 AND locate('>', Dirty, locate('<', Dirty)) > 0 
    DO 
    BEGIN 
     SET iStart = locate('<', Dirty), iEnd = locate('>', Dirty, locate('<', Dirty)); 
     SET iLength = (iEnd - iStart) + 1; 
     IF iLength > 0 THEN 
     BEGIN 
      SET Dirty = insert(Dirty, iStart, iLength, ''); 
     END; 
     END IF; 
    END; 
    END WHILE; 
    RETURN Dirty; 
END 
+2

Hice un pequeño punto de referencia aproximado en 5000 (~ 20mb) varias muestras de texto sin formato/html (descripciones de trabajo raspado). La salida de su ejemplo es exactamente la misma que la de Boann, sin embargo su código tomó ~ 32s para procesar y Boann solo 7s haciendo ** la solución de Boann 4.5x más rápida **. Solo estoy poniendo esto aquí para futuras referencias si alguien enfrenta el mismo dilema que yo. Gracias a ambos, chicos. –

1

Boann's funciona una vez que haya agregado SET $str = COALESCE($str, '');.

de esta post:

también tomar nota, es posible que desee poner un SET $ cadena = COALESCE ($ cadena, ''); justo antes del bucle; de ​​lo contrario, los valores nulos pueden provocar una consulta final interrumpe/nunca . - Tom C17 de agosto a las 9:51

1

estoy usando la biblioteca lib_mysqludf_preg para esto y una expresión regular como esto:

SELECT PREG_REPLACE('#<[^>]+>#',' ',cell) FROM table; 

también lo hizo así por filas, que con las entidades HTML codificados:

SELECT PREG_REPLACE('#&lt;.+?&gt;#',' ',cell) FROM table; 

Probablemente hay casos en que estos pueden fallar pero no he encontrado ninguno y son razonablemente rápidos.

0

Acabo de ampliar la respuesta @boann para permitir la orientación de cualquier etiqueta específica para que podamos reemplazar las etiquetas una por una con cada llamada a la función. Solo necesita pasar el parámetro de etiqueta, p. 'a' para reemplazar todas las etiquetas de anclaje de apertura/cierre. Esto responde a la pregunta formulada por OP, a diferencia de la respuesta aceptada, que elimina TODAS las etiquetas.

# MySQL function to programmatically replace out specified html tags from text/html fields 

# run this to drop/update the stored function 
DROP FUNCTION IF EXISTS `strip_tags`; 

DELIMITER | 

# function to nuke all opening and closing tags of type specified in argument 2 
CREATE FUNCTION `strip_tags`($str text, $tag text) RETURNS text 
BEGIN 
    DECLARE $start, $end INT DEFAULT 1; 
    SET $str = COALESCE($str, ''); 
    LOOP 
     SET $start = LOCATE(CONCAT('<', $tag), $str, $start); 
     IF (!$start) THEN RETURN $str; END IF; 
     SET $end = LOCATE('>', $str, $start); 
     IF (!$end) THEN SET $end = $start; END IF; 
     SET $str = INSERT($str, $start, $end - $start + 1, ''); 
     SET $str = REPLACE($str, CONCAT('</', $tag, '>'), ''); 
    END LOOP; 
END; 

| DELIMITER ; 

# test select to nuke all opening <a> tags 
SELECT 
    STRIP_TAGS(description, 'a') AS stripped 
FROM 
    tmpcat; 

# run update query to replace out all <a> tags 
UPDATE tmpcat 
SET 
    description = STRIP_TAGS(description, 'a'); 
Cuestiones relacionadas