sed no puede eliminar el carácter de nueva línea

12

He estado usando seddurante bastante tiempo, pero aquí hay una peculiaridad que encontré, que no puedo resolver.

Déjame explicarte mi problema con el caso real.


Escena 1

printf "ls" | xclip -selection clipboard
echo "ls" | xclip -selection clipboard

En el primer comando, canalizo la printfsalida a xclippara que se copie en el portapapeles. Ahora, a printfdiferencia echo, no inserta una nueva línea al final de forma predeterminada. Entonces, si pego este contenido en la terminal, el lscomando que se copia no se ejecuta automáticamente.

En el segundo, hay una nueva línea al final, por lo que al pegar el contenido del portapapeles también se ejecuta el comando en el portapapeles.

Esto no es deseable para mí. Entonces, quería eliminar la nueva línea usando sed, pero falló, como se explica en la escena a continuación.

Escena # 2

echo "ls" | sed -r 's/\n//g' | xclip -selection clipboard

El contenido en el portapapeles todavía contiene nueva línea. Cuando lo pego en la terminal, el comando se ejecuta automáticamente.

También intenté eliminar el carácter de retorno de carro \r. Pero nada Parece que me estoy perdiendo algo muy crucial / básico aquí.

shivams
fuente

Respuestas:

16

seddelimitaciones en \newlines: siempre se eliminan en la entrada y se vuelven a insertar en la salida. No es que nunca un \ncarácter ewline en un sedespacio de patrones que no se producen como resultado de una edición que haya realizado. Nota: con la excepción de GNU sed's -zmodo de ...

Solo usa tr:

echo ls | tr -d \\n | xclip -selection clipboard

O, mejor aún, olvídate por sedcompleto:

printf ls | xclip -selection clipboard
mikeserv
fuente
Esto eliminará todas las nuevas líneas, a menudo no deseable en el generate-text | xclipcaso. Esta respuesta solo elimina la última línea nueva.
Tom Hale
7

Muchas herramientas de procesamiento de texto, incluido sed, operan en el contenido de la línea, excluyendo el carácter de nueva línea. Lo primero que hace sed al procesar una línea es quitar la nueva línea al final, luego ejecuta los comandos en el script y agrega una nueva línea final al imprimir. Por lo tanto, no podrá eliminar la nueva línea con sed.

Para eliminar todas las nuevas líneas, puede usar tren su lugar:

echo "ls" | tr -d '\n' | xclip

Gilles 'SO- deja de ser malvado'
fuente
4

Puede reemplazar las nuevas líneas en sed pasándole la opción -z .

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

Página del manual de Sed:

-z, - líneas separadas de datos nulos por caracteres NUL

JSON C11
fuente
Esto eliminará todas las líneas nuevas, lo que generalmente no se desea en el | xclipcaso.
Tom Hale
2

Si solo está poniendo comandos en el portapapeles

echo -n "ls " | xclip -selection clipboard

Si además necesita realizar transformaciones más complejas,

echo "ls  " | perl -pe 's/\n//' | xclip -selection clipboard
JJoao
fuente
Hmm Solución lisa Supongo que tal vez es hora de pasar a Perl o Python para expresiones regulares.
Shivams
3
@shivams, perly pythonson mucho más lentos de lo que sedpueden ser cuando se usan correctamente. Sin embargo, aprender a usarlo correctamente es la clave.
mikeserv
@mikeserv - Estoy de acuerdo; especial para oneliner sed es maravilloso. Si las transformaciones se van a volver más complejas, entonces prefiero perl / python / gawk.
JJoao
1
@JJoa: Su preferencia es la suya, pero sedpuede hacer mucho más que manejar solo sus frases ingeniosas , y probablemente puede hacerlo más rápido que cualquiera de esas otras herramientas que menciona.
mikeserv
1
@mikeserv: una vez más, estoy de acuerdo contigo. Hace un año tenía un sistema de traducción EN-PT escrito en sed (20000 s /.../.../), generado por sed! ¡Y funcionó! Más tarde se convirtió en Perl, para tener matrices, hashes, funciones, paquetes y CPAN.
JJoao
1

Para eliminar solo la última línea nueva , pase por:

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