Bash: separa el salto de línea final de la salida

189

Cuando ejecuto comandos en Bash (o para ser específicos wc -l < log.txt), la salida contiene un salto de línea después. ¿Como me deshago de esto?

hexacianuro
fuente

Respuestas:

251

Si su salida esperada es una sola línea , simplemente puede eliminar todos los caracteres de nueva línea de la salida. No sería raro canalizar a la utilidad 'tr', o a Perl si lo prefiere:

wc -l < log.txt | tr -d '\n'

wc -l < log.txt | perl -pe 'chomp'

También puede usar la sustitución de comandos para eliminar la nueva línea final:

echo -n "$(wc -l < log.txt)"

printf "%s" "$(wc -l < log.txt)"

Tenga en cuenta que no estoy de acuerdo con la decisión del OP de elegir la respuesta aceptada. Creo que uno debe evitar usar 'xargs' cuando sea posible. Sí, es un juguete genial. No, no lo necesitas aquí.


Si su salida esperada puede contener varias líneas , debe tomar otra decisión:

Si desea eliminar MÚLTIPLES caracteres de nueva línea del final del archivo, nuevamente use la sustitución cmd:

printf "%s" "$(< log.txt)"

Si desea eliminar estrictamente EL ÚLTIMO carácter de nueva línea de un archivo, use Perl:

perl -pe 'chomp if eof' log.txt


Tenga en cuenta que si está seguro de tener un carácter de nueva línea final que desea eliminar, puede usar 'head' de GNU coreutils para seleccionar todo excepto el último byte. Esto debería ser bastante rápido:

head -c -1 log.txt

Además, para completar, puede verificar rápidamente dónde están sus caracteres de nueva línea (u otros caracteres especiales) en su archivo usando 'cat' y la bandera 'show-all'. El carácter del signo de dólar indicará el final de cada línea:

cat -A log.txt
Steve
fuente
Esto elimina TODAS las nuevas líneas de la salida, no solo la nueva línea final como lo pide el título.
Cody A. Ray
@ CodyA.Ray: Sin embargo, debe aceptar que la pregunta describe un comando específico que solo producirá una sola línea de salida. Sin embargo, he actualizado mi respuesta para adaptarla al caso más general. HTH
Steve
3
Esto sería mejor si las opciones cortas fueran reemplazadas por opciones largas. Las opciones largas enseñan y funcionan, por ejemplo tr --delete '\n'.
Elijah Lynn el
1
También lo hice| tr -d '\r'
AlikElzin-kilaka
Vale la pena señalar que la solución de sustitución cmd podría conducir a una línea demasiado larga si el archivo es muy grande.
phk
88

De una sola mano:

wc -l < log.txt | xargs echo -n
Satya
fuente
24
Mejor:echo -n `wc -l log.txt`
Satya
9
¿Por qué es mejor ejecutar comandos en backticks que usar una tubería?
Matthew Schinckel
2
Estos no solo eliminarán las nuevas líneas finales, sino que también exprimirán los espacios en blanco consecutivos (más precisamente, según lo definido por IFS) en un espacio. Ejemplo: echo "a b" | xargs echo -n; echo -n $(echo "a b"). Esto puede o no ser un problema para el caso de uso.
musiphil
14
Peor aún, si la salida comienza con -e, se interpretará como la opción echo. Siempre es más seguro de usar printf '%s'.
musiphil
1
xargses muy lento en mi sistema (y sospecho que también lo es en otros sistemas), por lo que printf '%s' $(wc -l log.txt)podría ser más rápido, ya printfque generalmente es una función incorporada (también porque no hay redirección de información). Nunca use backticks, han quedado en desuso en las nuevas versiones de POSIX y tienen numerosos inconvenientes.
yyny
14

También hay soporte directo para la eliminación de espacios en blanco en la sustitución de variables Bash :

testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}
Andrey Taranov
fuente
1
También puedes usartrailing_linebreak_removed=${testvar%?}
PairedPrototype
Tenga en cuenta que si está utilizando la sustitución de comandos, entonces no necesita hacer nada para eliminar las nuevas líneas finales. Bash ya lo hace como parte de la sustitución de comandos: gnu.org/software/bash/manual/html_node/…
Michael Burr
10

Si asigna su salida a una variable, bashelimina automáticamente los espacios en blanco:

linecount=`wc -l < log.txt`
nneonneo
fuente
10
Las nuevas líneas finales se eliminan, para ser exactos. Es la sustitución de comandos lo que los elimina, no la asignación de variables.
chepner
2
He visto en Cygwin bash que el espacio en blanco al final no se elimina al usar $ (cmd / c echo% VAR%). En este caso, tuve que usar $ {var %% [[: space:]]}.
Andrey Taranov
1
Nota: no es la asignación de variables, sino la expansión de la expresión lo que elimina las nuevas líneas.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
10

printf ya recorta la nueva línea final para usted:

$ printf '%s' $(wc -l < log.txt)

Detalle:

  • printf imprimirá su contenido en lugar del %smarcador de posición de cadena.
  • Si no le dice que imprima una nueva línea ( %s\n), no lo hará.
zero2cx
fuente
77
Si coloca comillas dobles alrededor del comando como "$(command)", las nuevas líneas internas se conservarán y solo se eliminará la nueva línea final . El shell está haciendo todo el trabajo aquí, printfes solo una forma de dirigir los resultados de la sustitución de comandos nuevamente stdout.
Brent Bradburn
2
No es printf lo que está quitando la nueva línea aquí, es el shell que lo está haciendo con la $( )construcción. Aquí está la prueba:printf "%s" "$(perl -e 'print "\n"')"
Flimm
Una vez más, vale la pena señalar que la línea de comando resultante podría ser demasiado larga.
phk
Esta es una solución conveniente con la sugerencia de @ nobar:$ printf '%s' "$(wc -l < log.txt)"
Ilias Karim
10

Si desea eliminar solo la última línea nueva , canalice a través de:

sed -z '$ s/\n$//'

sedno agregará a \0al final de la secuencia si el delimitador se establece en NULvia -z, mientras que para crear un archivo de texto POSIX (definido para terminar en a \n), siempre generará un final \nsin -z.

P.ej:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender

Y para probar no NULañadido:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
00000000: 666f 6f0a 6261 72                        foo.bar

Para eliminar varias líneas nuevas finales , canalice a través de:

sed -Ez '$ s/\n+$//'
Tom Hale
fuente
Supongo que esta es una extensión de GNU, Mac sedno proporciona -z.
Spidey
7

Si desea imprimir la salida de cualquier cosa en Bash sin final de línea, repítala con el -ninterruptor.

Si ya lo tiene en una variable, repítalo con la nueva línea final recortada:

    $ testvar=$(wc -l < log.txt)
    $ echo -n $testvar

O puede hacerlo en una línea, en su lugar:

    $ echo -n $(wc -l < log.txt)
Rastislav Hasicek
fuente
2
La variable es técnicamente innecesaria. echo -n $(wc -l < log.txt)tiene el mismo efecto
chepner