encoding - utiliza - hacer doble grep
¿Cómo hacer un grep insensible a los acentos? (3)
No creo que esto se pueda hacer en grep, a menos que esté dispuesto a escribir un script de shell que use iconv
y diff
, que sería un poco visualmente diferente de lo que está solicitando.
Aquí hay algo muy cercano a su solicitud a través de un script rápido de Perl:
#!/usr/bin/perl
# tgrep 0.1 Copyright 2014 by Adam Katz, GPL version 2 or later
use strict;
use warnings;
use open qw(:std :utf8);
use Text::Unidecode;
my $regex = shift or die "Missing pattern./nUsage: tgrep PATTERN [FILE...]";
my $retval = 1; # default to false (no hits)
while(<>) {
my $line = "", my $hit = 0;
while(//G(/S*(?:/s+|$))/g){ # for each word (w/ trailing spaces)
my $word = $1;
if(unidecode($word) =~ qr/$regex/) { # if there was a match
$hit++; # note that fact
$retval = 0; # final exit code will be 0 (true)
$line .= "/e[1;31m$word/e[0;0m"; # display word in RED
} else {
$line .= $word; # display non-matching word normally
}
}
print $line if $hit; # only display lines with matches
}
exit $retval;
Markdown no me permite hacer texto en rojo, así que aquí está el resultado con los hits entre comillas:
$ echo "match àei but also äēì and possibly æi" | tgrep aei
match "àei" but also "äēì" and possibly "æi"
Esto resaltará las palabras coincidentes en lugar de la coincidencia real, lo que sería muy difícil de hacer sin crear clases de caracteres masivos y / o componer un analizador de expresiones regulares por partes. Por lo tanto, buscar el patrón "ae" en lugar de "aei" produciría los mismos resultados (en este caso).
Ninguno de los indicadores de grep se replica en este ejemplo de juguete. Yo quería mantenerlo simple.
¿Hay alguna forma de hacer una búsqueda insensible al acento con grep, preferiblemente manteniendo la opción --color? Con esto quiero decir grep --secret-accent-insensitive-option aei
coincidiría con aei pero también con äēì y posiblemente con æi.
Sé que puedo usar iconv -t ASCII//TRANSLIT
para eliminar acentos de un texto, pero no veo cómo puedo usarlo para que coincida, ya que el texto se transforma (podría funcionar para grep -c o -l)
Realmente más rápido que la solución perl para mí que usa grep de php (se puede adaptar).
Strtolower su cadena de consulta sin acentos, luego reemplace algunas letras con sus formas de acento, y grep -i para las investigaciones de casos insensibles (tenga cuidado con las cotizaciones en $ q):
// Your query string
$q = ''Maxime Bernié'';
$accents = array(
''a'' => ''[aáàâäãå]'',
''e'' => ''[eéèêë]'',
''i'' => ''[iíìîï]'',
''o'' => ''[oóòôöõ]'',
''u'' => ''[uúùûü]'',
''c'' => ''[cç]'',
''n'' => ''[nñ]'',
''y'' => ''[ýÿ]''
);
$q = remove_accents(strtolower($q));
$qa = str_split($q);
foreach ($qa as $k => $v) {
if (isset($accents[$v])) {
$qa[$k] = $accents[$v];
}
}
$q = implode('''', $qa);
echo system(''cat file.txt | grep -i "''.$q.''"'');
function remove_accents($str, $charset=''utf-8'')
{
$str = htmlentities($str, ENT_NOQUOTES, $charset);
$str = preg_replace(''#&([A-za-z])(?:acute|cedil|caron|circ|grave|orn|ring|slash|th|tilde|uml);#'', ''/1'', $str);
$str = preg_replace(''#&([A-za-z]{2})(?:lig);#'', ''/1'', $str);
$str = preg_replace(''#&[^;]+;#'', '''', $str);
return $str;
}
(Disculpas por la publicación doble, pero esta es definitivamente una respuesta distinta. Esta también es la respuesta correcta . Solo me enteré hace unos minutos).
Usted está buscando una gran cantidad de clases de equivalencia de expresiones regulares POSIX:
14.3.6.2 Operadores de clase de equivalencia (
[= … =]
)Regex reconoce las expresiones de clase de equivalencia dentro de las listas. Una expresión de clase de equivalencia es un conjunto de elementos de clasificación que pertenecen a la misma clase de equivalencia. Se forma una expresión de clase de equivalencia colocando un elemento de clasificación entre un operador de clase de equivalencia abierta y un operador de clase de equivalencia cerrada .
[=
representa el operador open-equivalence-class y=]
representa el operador close-equivalence-class. Por ejemplo, sia
yA
fueran una clase de equivalencia, entonces tanto[[=a=]]
como[[=A=]]
coincidirían cona
y conA
Si el elemento de clasificación en una expresión de clase de equivalencia no es parte de una clase de equivalencia, entonces el emparejador considera que la expresión de clase de equivalencia es un símbolo de clasificación.
Estoy usando carpos en la línea siguiente para indicar qué es realmente coloreado. También pellizqué la cadena de prueba para ilustrar un punto sobre el caso.
$ echo "I match àei but also äēì and possibly æi" | grep ''[[=a=]][[=e=]][[=i=]]''
I match àei but also äēì and possibly æi
^^^ ^^^
Esto coincide con todas las palabras como aei
. El hecho de que no concuerde con æi
debe ser un recordatorio de que estás comprometido con el mapeo que existe en la biblioteca de expresiones regulares que estás utilizando (presumiblemente gnulib, que es lo que he vinculado y citado), aunque creo que es bastante probable que los dígrafos están más allá del alcance incluso del mejor mapa de clase de equivalencia.
No debe esperar que las clases de equivalencia sean portátiles ya que son demasiado arcanas.
Llevando esto un paso más allá, si solo desea caracteres acentuados, las cosas se vuelven mucho más complicadas. Aquí cambié tu solicitud de aei
a [aei]
.
$ echo "I match àei but also äēì and possibly æi" | grep ''[[=a=][=e=][=i=]]''
I match àei but also äēì and possibly æi
^ ^ ^^^ ^ ^^^ ^ ^ ^
Limpiar esto para evitar coincidencias sin acentos requeriría tanto clases de equivalencia como look-ahead / look-behind, y aunque BRE (basic reexx POSIX) y ERE (regex POSIX extendido) son compatibles con el primero, ambos carecen del último. Libpcre (la biblioteca de C para expresiones regulares compatibles con perl que grep -P
y la mayoría usa) y perl
admite lo último pero carecen de lo anterior:
Prueba # 1: grep
con libpcre: falla
$ echo "I match àei but also äēì and possibly æi" /
| grep -P ''[[=a=][=e=][=i=]](?<![aei])''
grep: POSIX collating elements are not supported
Prueba # 2: perl
mismo: falla
$ echo "I match àei but also äēì and possibly æi" /
| perl -ne ''print if /[[=a=][=e=][=i=]](?<![aei])/''
POSIX syntax [= =] is reserved for future extensions in regex; marked by <-- HERE in m/[[=a=][=e= <-- HERE ][=i=]](?<![aei])/ at -e line 1.
Pruebe # 3: python
(que tiene su propia implementación PCRE): falla (silenciosa)
$ echo "I match àei but also äēì and possibly æi" /
| python -c ''import re, sys;
print re.findall(r"[[=a=][=e=][=i=]]", sys.stdin.read())''
[]
¡Vaya, una característica de expresiones regulares que PCRE, python
e incluso perl
no admiten! No hay muchos de esos. (No importa que la queja esté en la segunda clase de equivalencia, todavía se queja dado solo /[[=a=]]/
.) Esto como evidencia adicional de que las clases de equivalencia son arcanas.
De hecho, parece que no hay bibliotecas PCRE capaces de clases de equivalencia; la sección sobre clases de equivalencia en regular-expressions.info afirma que solo las bibliotecas de expresiones regulares que implementan el estándar POSIX en realidad tienen este soporte. GNU grep
acerca más, ya que puede hacer BRE, ERE y PCRE, pero no puede combinarlos.
Entonces lo haremos en dos partes.
Prueba el n. ° 4: trucos desagradables: éxito
$ echo "I match àei but also äēì and possibly æi" /
| grep --color=always ''[[=a=][=e=][=i=]]'' /
| perl -pne "s//e/[${GREP_COLOR:-01;31}m/e/[K(?i)([aei])//$1/g"
I match àei but also äēì and possibly æi
^ ^^^
Caminata del código:
-
grep
fuerza el color para queperl
puedaperl
los códigos de color para observar las coincidencias -
${GREP_COLOR:-01;31}
toma nota del color degrep
(con el mismo color rojo brillante predeterminado) -
s///
comandos///
perl
coincide con el código de color completo y luego con las letras sin acentos que queremos eliminar de los resultados finales. Reemplaza todo eso con las letras (sin color) - Cualquier cosa después de
(?i)
en elperl
regex es insensible a mayúsculas ya que[[=i=]]
coincide conI
-
perl -p
imprime cada línea de su entrada una vez completada su ejecución-e
Para obtener más información sobre BRE vs ERE frente a PCRE y otros, consulte esta publicación regular de StackExchange o las expresiones regulares de POSIX en regular-expressions.info . Para obtener más información sobre las diferencias por idioma (incluyendo libpcre vs python PCRE vs perl), busque herramientas en regular-expressions.info .