¿Por qué xkvbd come nuevas líneas cuando se alimenta desde xsel?

¿Por qué xkvbd come nuevas líneas cuando se alimenta desde xsel?

Tengo este script que asigno a un atajo de teclado para simular el pegado mediante clic central:

#!/bin/bash
aa=0
for randstring in `xsel`
do
  if [[ "$randstring" =~ [ěščřžýáíéúůóťďň] ]]
  then
      xxx=`xsel|sed 's/ě/\\\[ecaron]/g' |sed 's/š/\\\[scaron]/g' |sed 's/č/\\\[ccaron] g' |sed 's/ř/\\\[rcaron]/g' |sed 's/ž/\\\[zcaron]/g' |sed 's/ý/\\\[yacute]/g' |sed 's/á/\\\[aacute]/g' |sed 's/í/\\\[iacute]/g' |sed 's/é/\\\[eacute]/g' |sed 's/ú/\\\[uacute]/g' |sed 's/ů/\\\[uring]/g'  |sed 's/ó/\\\[oacute]/g' |sed 's/ď/\\\[dcaron]/g' |sed 's/ň/\\\[ncaron]/g' |sed 's/ť/\\\[tcaron]/g'  |sed ':a;N;$!ba;s/\n/\\n/g'`
      xvkbd -text "$xxx" 2>/dev/null
      aa=1
      break
  else
    aa=0
  fi
done
if [[ $aa -eq 0 ]]
    then
        xsel | xvkbd  -file - 2>/dev/null
fi

Lo uso -textcon xvkbd cuando el texto está en checo (mi idioma) porque xvkbd no entiende signos diacríticos como ě sino solo en forma como \[ecaron]. Ahora, con esta opción, si hay una nueva línea int xsel, no se imprime con xvkbd. Sin embargo, cuando lo hago

xx="---8<-----\nToday date is: $(date +%Y%m%d)\n---8<-----" 
xvkbd -text "$xx"  2>/dev/null

Las nuevas líneas se imprimen.

Sospecho que el problema está en la última expresión sed sed ':a;N;$!ba;s/\n/\\n/g', pero no sé cómo mejorarla. ¿Creo que necesito cuidarlos \nde alguna manera?

Respuesta1

EDITAR: Encontré el problema, pero aún así vale la pena leer el resto para cuando realmente quieras una nueva línea final `...

Te falta un extra \\o incluso solo\

  sed ':a;N;$!ba;s/\n/\\\\n/g'`  

MÁS INFORMACIÓN: Respecto al tema de $( )vs backquotes para command substitution, mencioné un comentario que puse a esta pregunta, aquí hay un extracto de man bash.

When  the  old-style  backquote form of substitution is used, backslash
retains its literal meaning except when followed by $, `,  or  \.   The
first backquote not preceded by a backslash terminates the command sub‐
stitution.  When using the $(command) form, all characters between  the
parentheses make up the command; none are treated specially.

--Publicación original--

No imprimirá el último \npero agrega intermedio \n en $xx...

Aquí hay una versión simplificada de su última sedllamada:

printf '%s\n' 'a\[ecaron]' b c '\[rcaron]d' |
   sed ':a;N;$!ba;s/\n/\\n/g' 

Producción:

a\[ecaron]\nb\nc\n\[rcaron]d

La razón por la que no tiene un final \n(en el ejemplo anterior) es que simplemente no habrá un carácter de nueva línea final en el espacio de patrón para la última línea (solo Nestarán allí los de finales de línea anteriores, a través de ) ... sedposteriormente generará el carácter de nueva línea final cuando salga, pero aun así, será devorado por xx=$(command substitution)by $( )o backticks...

Para incluir una final \n, solo necesita una sustitución final.

sed ':a;N;$!ba;s/\n/\\n/g;s/$/\\n/'

¿O es que no estás obteniendo ni siquiera los \ns intermedios?


Sólo una nota al margen: no es necesario tener innumerablessedsllamando a tantos procesos. Puede concatenarlos mediante ;(dos puntos), por ejemplo. sed 's/ě/\\\[ecaron]/g; s/š/\\\[scaron]/g; .... o ni siquiera usar los dos puntos y simplemente poner cada expresión de sustitución en una nueva línea... lo que les permite alinearse muy bien...

información relacionada