sheet regular cheat regex perl sed html-parsing text-extraction

regex - cheat - gsub regular expression r



Cómo extraer cadenas siguiendo un patrón con GREP, REGEX o PERL (8)

Aquí hay una solución que usa HTML tidy & xmlstarlet:

htmlstr='' <table name="content_analyzer" primary-key="id"> <type="global" /> </table> <table name="content_analyzer2" primary-key="id"> <type="global" /> </table> <table name="content_analyzer_items" primary-key="id"> <type="global" /> </table> '' echo "$htmlstr" | tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null | sed ''/type="global"/d'' | xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v ''@name'' -n

Tengo un archivo que se ve así:

<table name="content_analyzer" primary-key="id"> <type="global" /> </table> <table name="content_analyzer2" primary-key="id"> <type="global" /> </table> <table name="content_analyzer_items" primary-key="id"> <type="global" /> </table>

Necesito extraer cualquier cosa dentro de las comillas que siguen a "name =", es decir, content_analyzer, content_analyzer2 y content_analyzer_items.

Estoy haciendo esto en una caja Linux, por lo que una solución que use sed, perl, grep o bash está bien.


Como necesita emparejar el contenido sin incluirlo en el resultado (debe coincidir con name=" pero no forma parte del resultado deseado) se requiere alguna forma de coincidencia de ancho cero o de captura de grupo. Esto se puede hacer fácilmente con las siguientes herramientas:

Perl

Con Perl podría usar la opción n para realizar un bucle línea por línea e imprimir el contenido de un grupo de captura si coincide:

perl -ne ''print "$1/n" if /name="(.*?)"/'' filename

GNU grep

Si tiene una versión mejorada de grep, como GNU grep, puede tener la opción -P disponible. Esta opción habilitará la expresión regular similar a Perl, lo que le permite usar /K que es una mirada abreviada detrás. Se restablecerá la posición de coincidencia, por lo que cualquier cosa antes de que sea de ancho cero.

grep -Po ''name="/K.*?(?=")'' filename

La opción o hace que grep imprima solo el texto coincidente, en lugar de toda la línea.

Vim - Editor de texto

Otra forma es usar un editor de texto directamente. Con Vim, una de las diversas formas de lograr esto sería eliminar líneas sin name= y luego extraer el contenido de las líneas resultantes:

:v/name=/d :%s//v.*name/="([^"]+)".*//1

Grep estándar

Si no tiene acceso a estas herramientas, por alguna razón, se podría lograr algo similar con grep estándar. Sin embargo, sin mirar alrededor requerirá un poco de limpieza más adelante:

grep -o ''name="[^"]*"'' filename

Una nota sobre el ahorro de resultados

En todos los comandos anteriores, los resultados se enviarán a stdout . Es importante recordar que siempre puede guardarlos conectándolo a un archivo al agregar:

> result

hasta el final del comando.


La expresión regular sería:

.+name="([^"]+)"

Entonces la agrupación estaría en el / 1


Se debe usar un analizador de HTML para este fin en lugar de expresiones regulares. Un programa Perl que hace uso de HTML::TreeBuilder :

Programa

#!/usr/bin/env perl use strict; use warnings; use HTML::TreeBuilder; my $tree = HTML::TreeBuilder->new_from_file( /*DATA ); my @elements = $tree->look_down( sub { defined $_[0]->attr(''name'') } ); for (@elements) { print $_->attr(''name''), "/n"; } __DATA__ <table name="content_analyzer" primary-key="id"> <type="global" /> </table> <table name="content_analyzer2" primary-key="id"> <type="global" /> </table> <table name="content_analyzer_items" primary-key="id"> <type="global" /> </table>

Salida

content_analyzer content_analyzer2 content_analyzer_items



Si la estructura de tu xml (o texto en general) es fija, la forma más fácil es usar cut . Para su caso específico:

echo ''<table name="content_analyzer" primary-key="id"> <type="global" /> </table> <table name="content_analyzer2" primary-key="id"> <type="global" /> </table> <table name="content_analyzer_items" primary-key="id"> <type="global" /> </table>'' | grep name= | cut -f2 -d ''"''


Vaya, el comando sed tiene que preceder al orden ordenado, por supuesto:

echo "$htmlstr" | sed ''/type="global"/d'' | tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null | xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v ''@name'' -n


esto podría hacerlo:

perl -ne ''if(m/name="(.*?)"/){ print $1 . "/n"; }''