Agarrando los primeros [x] caracteres para una cadena de una tubería


Respuestas:


82

Una forma es usar cut:

 command | cut -c1-8

Esto le dará los primeros 8 caracteres de cada línea de salida. Como cutes parte de POSIX, es probable que esté en la mayoría de los Unices.


3
Tenga en cuenta que cut -cselecciona caracteres; cut -bo head -cselecciona bytes. Esto marca la diferencia en algunos entornos locales (en la práctica, cuando se usa UTF-8).
Gilles 'SO- deja de ser malvado'

Tampoco tiene que especificar el índice de inicio en este caso. El refrán cut -c-8seleccionará del personaje 1 al 8.
Sparhawk

@Steven, cutes equivalente en Windows?
Pacerier

También command | dd bs=8 count=1 2>/dev/null. No digo que sea más corto o superior. Solo otra alternativa.
dubiousjim

@Gilles, pero tenga en cuenta que con las versiones actuales de GNU cut, cut -cfunciona como cut -b(es decir, no funciona correctamente para caracteres de varios bytes).
Stéphane Chazelas

24

Estas son algunas otras formas de obtener solo los primeros 8 caracteres.

command | head -c8

command | awk '{print substr($0,1,8);exit}' 

command | sed 's/^\(........\).*/\1/;q'

Y si tienes bash

var=$(command)
echo ${var:0:8}

2
Creo que la siguiente formulación sed es un poco más fácil de leer: command | sed 's/\(.\{8\}\).*/\1/'o si su sed lo admite: command | sed -r 's/(.{8}).*/\1/'; De lo contrario, +1
Steven D

Cosas buenas, pero tenga en head -ccuenta que cuenta bytes , no caracteres. De manera similar, entre las principales implementaciones de Awk, solo GNU awk maneja los caracteres de varios bytes correctamente; FreeBSD Awk y Mawk no lo hacen.
mklement0

2

Si tiene un shell suficientemente avanzado (por ejemplo, lo siguiente funcionará en Bash, no estoy seguro sobre el guión), puede hacer lo siguiente:

read -n8 -d$'\0' -r <(command)

Después de ejecutar read ... <(command), tus personajes estarán en la variable de shell REPLY. Escriba help readpara conocer otras opciones.

Explicación: el -n8argumento readdice que queremos hasta 8 caracteres. El -d$'\0'dicho lee hasta un nulo, en lugar de una nueva línea. De esta manera, la lectura continuará para 8 caracteres incluso si uno de los caracteres anteriores es una nueva línea (pero no si es nulo). Una alternativa -n8 -d$'\0'es usar -N8, que lee exactamente 8 caracteres o hasta que el stdin alcanza EOF. No se honra ningún delimitador. Eso probablemente se adapte mejor a sus necesidades, pero no sé de antemano cuántos proyectiles tienen una lectura que honra -Nen lugar de honrar -ny -d. Continuando con la explicación: -rdice ignore \-escapes, de modo que, por ejemplo, tratemos \\como dos caracteres, en lugar de uno solo \.

Finalmente, lo hacemos en read ... <(command)lugar de hacerlo command | read ...porque en la segunda forma, la lectura se ejecuta en una subshell que luego se cierra inmediatamente, perdiendo la información que acaba de leer.

Otra opción es hacer todo el procesamiento dentro de la subshell. Por ejemplo:

$ echo abcdefghijklm | { read -n8 -d$'\0' -r; printf "REPLY=<%s>\n" "$REPLY"; }
REPLY=<abcdefgh>

1
Si solo desea generar los 8 caracteres y no necesita procesarlos en el shell, simplemente utilícelos cut.
dubiousjim

Es bueno saberlo read -n <num>; pequeña advertencia: Bash 3.x (aún actual en el sistema operativo) interpreta erróneamente <num>como un recuento de bytes y, por lo tanto, falla con caracteres de varios bytes; Esto se ha solucionado en Bash 4.x.
mklement0

Esta es una gran y útil respuesta. Mucho más general que los demás.
not2qubit

2

Otra solución única mediante el uso de expansión de parámetros

echo ${word:0:x}

EG: word="Hello world"
echo ${word:0:3} or echo ${word::3} 
o/p: Hel


EG.2: word="Hello world"
echo ${word:1:3}
o/p: ell

También puede usar una variable que contenga la longitud, por ejemplo: en x=8; echo ${word:0:$x}lugar de codificar el número entero.
Cometsong

1

Esto es portátil:

a="$(command)"             # Get the output of the command.
b="????"                   # as many ? as characters are needed.
echo ${a%"${a#${b}}"}      # select that many chars from $a

Construir una cadena de caracteres de longitud variable tiene su propia pregunta aquí .


0

Tuve este problema al generar manualmente archivos de suma de comprobación en el repositorio maven. Desafortunadamente, cut -csiempre imprime una nueva línea al final de la salida. Para suprimir que uso xxd:

command | xxd -l$BYTES | xxd -r

Produce exactamente $BYTESbytes, a menos que la commandsalida de 's sea más corta, entonces exactamente esa salida.


otro método para despegar cutde la nueva línea final es introducirlo en:| tr -d '\n'
Cometsong
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.