Quiero saber cómo usar greppara mostrar todas las líneas que comienzan y terminan con el mismo carácter.
Quiero saber cómo usar greppara mostrar todas las líneas que comienzan y terminan con el mismo carácter.
Respuestas:
POSIXY:
pattern='\(.\).*\1
.'
grep -x -- "$pattern" file
No funcionará si la línea comienza o termina con un carácter de byte no válido, si desea cubrir ese caso, puede agregar LC_ALL=C, aunque LC_ALL=Csolo funciona con datos de caracteres de un solo byte.
perl6 parece ser la mejor herramienta, si la tiene en su caja:
$ printf '\ue7\u301 blah \u107\u327\n121\n1\n123\n' |
perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
ḉ blah ḉ
121
1
Aunque todavía se ahoga con caracteres no válidos.
Tenga en cuenta que perl6alterará su texto convirtiéndolo en NFCforma:
$ printf '\u0044\u0323\u0307\n' |
perl6 -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+1e0c
U+0307
U+000a
$ printf '\u0044\u0323\u0307\n' |
perl -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+0044
U+0323
U+0307
U+000a
Internamente, perl6almacena la cadena en NFGforma (soporte Normalization Form Grapheme), que es una perl6forma inventada de tratar correctamente los grafemas no precompuestos:
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.chars.say'
1
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.codes.say'
2
perl6embargo, debe tenerse en cuenta que alterará el texto (gírelo a NFC (formulario de normalización "compuesto")).
perl6se almacena en NFGforma ( Gfor Grapheme), que es una perl6forma de tratar correctamente los grafemas no precompuestos.
No grep pero awk:
awk -F "" 'NF && $1 == $NF'
Estos casos especiales se manejan:
Un FS vacío divide el registro en un solo personaje por campo en gawk, mawky busybox awk(bytes, no caracteres de los dos últimos), pero no es estándar y no funciona en las implementaciones de la awkderiva de la original por A, W y K como en BSD y unidades comerciales. Más portátil pero más para escribir:
awk '/./ && substr($0,1,1) == substr($0,length)'
FScomo cadena vacía no es estándar, y no funcionará en alguna awkimplementación.
awk 'length&&substr($0,1,1)==substr($0,length)'(observe el argumento predeterminado de lengthis $0, y la acción predeterminada es {print $0})
nawkcual es casi tan malo :-)
grep -xe '\(.\).*\1' -e .
Ejemplo:
$ printf '%s\n' il y était cet été | grep -xe '\(.\).*\1' -e .
y
été
-xes para la coincidencia exacta (coincidencia en toda la línea). \1siendo una referencia al personaje capturado en \(.\). Agregamos un -e .para cuidar el caso especial de una línea que contiene un solo carácter.
Se supone que la entrada contiene texto válido en la configuración regional actual.
La coincidencia está en el carácter , no en el byte (esos é en UTF-8 son los dos bytes 0xc3 0xa9 por ejemplo), ni en el grupo de gráficos (no funcionaría si esos é se escribieran en su forma descompuesta cone seguido por U + 0301 combinando acento agudo, por ejemplo).
Para trabajar en clústeres de gráficos, con un grepsoporte -Ppara PCRE:
$ printf 'e\u0301te\u0301\n' | grep -xPe '(\X).*\1|\X'
été
Eso supone que la descomposición es la misma para los dos grupos, por ejemplo, un ḉexpresado como c U+0301 U+0327no coincidiría con uno expresado como c U+0327 U+0301o ć( U+0107) U+0327o ç( U+00E7) U+0301o ḉ ( U+1E09). Para eso, deberías hacer la verificación en un formulario normalizado:
$ printf '\ue7\u301 blah \u107\u327\n' |
perl -MUnicode::Normalize -C -ne '
print if /^\X$/ || NFC($_) =~ /^(\X).*\1$/'
ḉ blah ḉ
perl6, perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'debería hacer todos los trabajos por usted.
Alternativa rápida a python2:
python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt
Ejemplo:
$ python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt | cat -A
nathan$
ookie $
a line a$