Tengo un archivo de texto que estoy enviando a una variable en mi script de shell. Sin embargo, solo necesito los primeros 50 caracteres.
He intentado usar cat ${filename} cut -c1-50pero obtengo mucho más que los primeros 50 caracteres. Eso puede deberse a la cutbúsqueda de líneas (no 100% seguro), mientras que este archivo de texto podría ser una cadena larga, realmente depende.
¿Hay alguna utilidad en la que pueda canalizar para obtener los primeros caracteres X de un catcomando?

|?cat ${filename} | cut -c1-50Respuestas:
Esto devuelve los primeros 50 bytes.
Tenga en cuenta que el comando no siempre se implementa de la misma manera en todos los sistemas operativos. En Linux y macOS se comporta de esta manera. En Solaris (11) necesita usar la versión gnu en / usr / gnu / bin /
fuente
-copción. Iría por dd (1) en su lugar.GNU coreutils 5.97) sí.-cSin embargo, POSIX no se define como una opción válida, por lo que definitivamente depende de su entorno local. unix.com/man-page/posix/1/headSu
cutcomando funciona si usa una tubería para pasarle datos:O, evitando un uso inútil del gato y haciéndolo un poco más seguro:
Tenga en cuenta que los comandos anteriores imprimirán los primeros 50 caracteres (o bytes, según su
cutimplementación) de cada línea de entrada . Debería hacer lo que espera si, como usted dice, su archivo es una línea enorme.fuente
Esto devuelve los primeros 50 bytes.
fuente
status=nonebandera. Use en su2>/dev/nulllugar (y cite correctamente):dd if="$filename" bs=1 count=50 2>/dev/null(aun así, considere usarbs=50 count=1para reducir la cantidad de llamadas al sistema involucradas).status=nonecuando usa Ubuntu 14.04, coreutils 8.21, pero tiene derecho a usarlo2>/dev/nullsi usa una versión anterior.read()de 50 bytes. Si,filepor ejemplo, es una tubería y hay menos caracteres disponibles en ese momento, se devolverán menos bytes. Para tener el equivalente dehead -c50, necesitarías usar el GNU específicoiflag=fullblock.La mayoría de las respuestas hasta ahora suponen que 1 byte = 1 carácter, lo que puede no ser el caso si está utilizando una configuración regional no ASCII.
Una forma un poco más robusta de hacerlo:
Tenga en cuenta que esto supone:
ksh93,bash(o un recientezshomksh(aunque el único conjunto de caracteres de varios bytes admitido pormkshUTF-8 y solo despuésset -o utf8-mode)) y una versión deheadese soporte-c(la mayoría lo hace hoy en día, pero no estrictamente estándar).locale charmapyfile -- "$filename"para verificar eso); si no, configúrelo con ie.LC_ALL=en_US.UTF-8)head, asumiendo el peor de los casos UTF-8 donde todos los caracteres están codificados en un máximo de 4 bytes. Esto debería cubrir la mayoría de los casos que se me ocurren.fuente
head, u otra implementación de la misma que agrega la-copción nōn-standard . Pero ya estás requiriendo GNU bash. (Nota:mkshel modo UTF-8 podría hacer esto para los archivos codificados UTF-8). Le preguntaría al OP si requieren octetos o caracteres multibyte, solo "caracteres" es un término vago / genérico.$filenameo$testStringno contiene nueva línea en blanco o comodines o comienza con-.${var:offset:length}construcción que está utilizando aquí en realidad provieneksh93y también es compatible con versiones recientes dezsh(zshtiene la suya propia$testString[1,50]). Necesitas${testString:0:50}enksh93yzshsin embargo.Otra variante (para la primera línea del archivo)
fuente
readyecho? Obash expansion?grep(regexp), y sí, el uso de shell aquí (pista: la primera línea puede ser grande). (Dicho esto, el bashism tampoco está en POSIX, pero la mayoría de los proyectiles lo implementan)1. Para archivos ASCII, haga como @DisplayName dice:
imprimirá los primeros 50 caracteres de file.txt, por ejemplo.
2. Para datos binarios, use
hexdumppara imprimirlos como caracteres hexadecimales:imprimirá los primeros 50 bytes de file.bin, por ejemplo.
Tenga en cuenta que sin la
-vopción detallada,hexdumpreemplazaría las líneas repetidas con un asterisco (*) en su lugar. Ver aquí: https://superuser.com/questions/494245/what-does-an-asterisk-mean-in-hexdump-output/494613#494613 .fuente
Puede usar sed para esto, que abordará el problema con bastante facilidad
fuente
sed -n -e '1s/^\(.\{50\}\).*/\1/p' ${filename}