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 está utilizando Perl, descargue un módulo para analizar XML: XML::Simple , XML::Twig o XML::LibXML . No reinventar la rueda.
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"; }''