Bash
El comando de corte
Buscar..
Introducción
El comando de cut
es una forma rápida de extraer partes de líneas de archivos de texto. Pertenece a los comandos más antiguos de Unix. Sus implementaciones más populares son la versión GNU que se encuentra en Linux y la versión FreeBSD que se encuentra en MacOS, pero cada versión de Unix tiene la suya. Vea a continuación las diferencias. Las líneas de entrada se leen desde la stdin
o desde los archivos enumerados como argumentos en la línea de comando.
Sintaxis
cortar -f1,3 # extraer el primer y tercer campo delimitado por tabuladores (desde stdin)
cortar -f1-3 # extraer desde el primer hasta el tercer campo (extremos incluidos)
corte -f-3 # -3 se interpreta como 1-3
cut -f2- # 2- se interpreta desde el segundo hasta el último
cortar -c1-5,10 # extraer de stdin los caracteres en las posiciones 1,2,3,4,5,10
cut -s -f1 # suprimir líneas que no contienen delimitadores
corte --complemento -f3 # (solo corte GNU) extraiga todos los campos excepto el tercero
Parámetros
Parámetro | Detalles |
---|---|
-f, - campos | Selección basada en el campo |
-d, --delimitador | Delimitador para selección de campo |
-c, --caracteres | Selección basada en caracteres, delimitador ignorado o error |
-s, - solo delimitado | Suprimir líneas sin caracteres delimitadores (impresos como están). |
--complemento | Selección invertida (extraer todos los campos / caracteres excepto los especificados |
- salida-delimitador | Especifique cuándo debe ser diferente del delimitador de entrada. |
Observaciones
1. Diferencias de sintaxis.
Las opciones largas en la tabla anterior solo son compatibles con la versión GNU.
2. Ningún personaje recibe tratamiento especial.
El cut
FreeBSD (que viene con MacOS, por ejemplo) no tiene el interruptor --complement
y, en el caso de los rangos de caracteres, se puede usar el comando colrm
lugar:
$ cut --complement -c3-5 <<<"123456789"
126789
$ colrm 3 5 <<<"123456789"
126789
Sin embargo, hay una gran diferencia, porque colrm
trata los caracteres TAB (ASCII 9) como tabulaciones reales hasta el siguiente múltiplo de ocho, y los espacios en blanco (ASCII 8) como -1 de ancho; por el contrario, cut
trata a todos los caracteres como una columna de ancho.
$ colrm 3 8 <<<$'12\tABCDEF' # Input string has an embedded TAB
12ABCDEF
$ cut --complement -c3-8 <<<$'12\tABCDEF'
12F
3. (Todavía no) Internacionalización
Cuando se diseñó el cut
, todos los caracteres tenían un byte de largo y la internacionalización no era un problema. Cuando los sistemas de escritura con caracteres más anchos se hicieron populares, la solución adoptada por POSIX fue diferenciar entre el viejo conmutador -c
, que debería conservar su significado de seleccionar caracteres, sin importar cuántos bytes de ancho, e introducir un nuevo conmutador -b
que debería Seleccione bytes, independientemente de la codificación de caracteres actual. En las implementaciones más populares, se introdujo -b
y funciona, pero -c
sigue funcionando exactamente igual que -b
y no como debería. Por ejemplo, con cut
GNU:
Parece que el filtro de correo no deseado de SE incluye listas negras de textos en inglés con caracteres kanji aislados. No pude superar esta limitación, por lo que los siguientes ejemplos son menos expresivos de lo que podrían ser.
# In an encoding where each character in the input string is three bytes wide,
# Selecting bytes 1-6 yields the first two characters (correct)
$ LC_ALL=ja_JP.UTF-8 cut -b1-6 kanji.utf-8.txt
...first two characters of each line...
# Selecting all three characters with the -c switch doesn’t work.
# It behaves like -b, contrary to documentation.
$ LC_ALL=ja_JP.UTF-8 cut -c1-3 kanji.utf-8.txt
...first character of each line...
# In this case, an illegal UTF-8 string is produced.
# The -n switch would prevent this, if implemented.
$ LC_ALL=ja_JP.UTF-8 cut -n -c2 kanji.utf-8.txt
...second byte, which is an illegal UTF-8 sequence...
Si sus caracteres están fuera del rango ASCII y desea utilizar el cut
, siempre debe tener en cuenta el ancho de caracteres en su codificación y utilizar -b
consecuencia. Si y cuando -c
comienza a funcionar como se documenta, no tendrá que cambiar sus scripts.
4. Comparaciones de velocidad.
Las limitaciones del cut
hacen que las personas duden de su utilidad. De hecho, la misma funcionalidad se puede lograr mediante utilidades más potentes y populares. Sin embargo, la ventaja del cut
es su rendimiento . Vea a continuación para algunas comparaciones de velocidad. test.txt
tiene tres millones de líneas, con cinco campos separados por espacios. Para la prueba awk
, se usó mawk
, porque es más rápido que GNU awk
. El shell en sí (última línea) es, con mucho, el peor desempeño. Los tiempos dados (en segundos) son lo que el comando de time
da como tiempo real .
(Solo para evitar malentendidos: todos los comandos probados dieron la misma salida con la entrada dada, pero por supuesto no son equivalentes y darían salidas diferentes en diferentes situaciones, en particular si los campos estuvieran delimitados por un número variable de espacios)
Mando | Hora |
---|---|
cut -d ' ' -f1,2 test.txt | 1.138s |
awk '{print $1 $2}' test.txt | 1.688s |
join -a1 -o1.1,1.2 test.txt /dev/null | 1.767s |
perl -lane 'print "@F[1,2]"' test.txt | 11.390s |
grep -o '^\([^ ]*\) \([^ ]*\)' test.txt | 22.925s |
sed -e 's/^\([^ ]*\) \([^ ]*\).*$/\1 \2/' test.txt | 52.122s |
while read ab _; do echo $a $b; done <test.txt | 55.582s |
5. Páginas de manual referenciales
Uso básico
El uso típico es con archivos de tipo CSV, donde cada línea consta de campos separados por un delimitador, especificados por la opción -d
. El delimitador predeterminado es el carácter TAB. Supongamos que tiene un archivo de datos data.txt
con líneas como
0 0 755 1482941948.8024
102 33 4755 1240562224.3205
1003 1 644 1219943831.2367
Entonces
# extract the third space-delimited field
$ cut -d ' ' -f3 data.txt
755
4755
644
# extract the second dot-delimited field
$ cut -d. -f2 data.txt
8024
3205
2367
# extract the character range from the 20th through the 25th character
$ cut -c20-25 data.txt
948.80
056222
943831
Como de costumbre, puede haber espacios opcionales entre un interruptor y su parámetro: -d,
es lo mismo que -d ,
GNU cut
permite especificar una opción --output-delimiter
: (una característica independiente de este ejemplo es que debe escaparse un punto y coma como delimitador de entrada para evitar su tratamiento especial por parte del shell)
$ cut --output-delimiter=, -d\; -f1,2 <<<"a;b;c;d"
a,b
Sólo un personaje delimitador.
No puede tener más de un delimitador: si especifica algo como -d ",;:"
, algunas implementaciones usarán solo el primer carácter como delimitador (en este caso, la coma). Otras implementaciones (por ejemplo, cut
GNU) darán un mensaje de error
$ cut -d ",;:" -f2 <<<"J.Smith,1 Main Road,cell:1234567890;land:4081234567"
cut: the delimiter must be a single character
Try `cut --help' for more information.
Los delimitadores repetidos se interpretan como campos vacíos
$ cut -d, -f1,3 <<<"a,,b,c,d,e"
a,b
es bastante obvio, pero con cadenas delimitadas por el espacio podría ser menos obvio para algunos
$ cut -d ' ' -f1,3 <<<"a b c d e"
a b
cut
no se puede usar para analizar argumentos como lo hace el shell y otros programas.
Sin citar
No hay forma de proteger el delimitador. Las hojas de cálculo y el software de manejo de CSV similar generalmente pueden reconocer un carácter de comillas de texto que hace posible definir cadenas que contienen un delimitador. Con el cut
no puedes.
$ cut -d, -f3 <<<'John,Smith,"1, Main Street"'
"1
Extraer, no manipular.
Solo puede extraer partes de líneas, no reordenar o repetir campos.
$ cut -d, -f2,1 <<<'John,Smith,USA' ## Just like -f1,2
John,Smith
$ cut -d, -f2,2 <<<'John,Smith,USA' ## Just like -f2
Smith