Quiero saber cómo usar grep
para mostrar todas las líneas que comienzan y terminan con el mismo carácter.
Quiero saber cómo usar grep
para 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=C
solo 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 perl6
alterará su texto convirtiéndolo en NFC
forma:
$ 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, perl6
almacena la cadena en NFG
forma (soporte Normalization Form Grapheme
), que es una perl6
forma 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
perl6
embargo, debe tenerse en cuenta que alterará el texto (gírelo a NFC (formulario de normalización "compuesto")).
perl6
se almacena en NFG
forma ( G
for Grapheme
), que es una perl6
forma 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
, mawk
y busybox
awk
(bytes, no caracteres de los dos últimos), pero no es estándar y no funciona en las implementaciones de la awk
deriva 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)'
FS
como cadena vacía no es estándar, y no funcionará en alguna awk
implementación.
awk 'length&&substr($0,1,1)==substr($0,length)'
(observe el argumento predeterminado de length
is $0
, y la acción predeterminada es {print $0}
)
nawk
cual es casi tan malo :-)
grep -xe '\(.\).*\1' -e .
Ejemplo:
$ printf '%s\n' il y était cet été | grep -xe '\(.\).*\1' -e .
y
été
-x
es para la coincidencia exacta (coincidencia en toda la línea). \1
siendo 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 grep
soporte -P
para 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+0327
no coincidiría con uno expresado como c
U+0327
U+0301
o ć
( U+0107
) U+0327
o ç
( U+00E7
) U+0301
o ḉ ( 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$