Por que o xkvbd está comendo novas linhas quando é alimentado pelo xsel?

Por que o xkvbd está comendo novas linhas quando é alimentado pelo xsel?

Eu tenho esse script que atribuo a um atalho de teclado para simular a colagem através do clique do meio:

#!/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

Eu uso -textxvkbd quando o texto está em tcheco (meu idioma) porque xvkbd não entende diacríticos como ě, mas apenas na forma como \[ecaron]. Agora, com esta opção, se houver uma nova linha int xsel, ela não será impressa com xvkbd. No entanto, quando eu faço

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

Novas linhas são impressas.

Suspeito que o problema esteja na última expressão sed sed ':a;N;$!ba;s/\n/\\n/g', mas não sei como melhorá-la. Eu acho que preciso cuidar \nde alguma forma?

Responder1

EDIT: Eu encontrei o problema, mas o resto ainda pode valer a pena ler quando você realmente quiser uma nova linha `...

Você está faltando um extra \\ou até mesmo apenas\

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

MAIS INFORMAÇÕES: Em relação à questão de $( )vs backquotes para command substitution, mencionei um comentário que fiz para esta questão, aqui está um trecho 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.

--Postagem Original--

Não imprimirá o último \n, mas adiciona intermediário \n em $xx...

Aqui está uma versão simplificada de sua última sedchamada:

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

Saída:

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

A razão pela qual não tem um final \n(no exemplo acima) é que simplesmente não haverá um caractere de nova linha no espaço padrão para a última linha (apenas aqueles de finais de linha anteriores, via N, estarão lá) ... sedposteriormente produzirá o caractere de nova linha final ao sair, mas mesmo assim, ele será engolido pelo xx=$(command substitution)by $( )ou backticks...

Para incluir um final \n, é necessária apenas uma substituição final.

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

Ou é o caso de você não estar conseguindo nem os intermediários \n?


Apenas uma observação: você não precisa ter muitossedschamando tantos processos. Você pode concatená-los via ;(dois pontos), por exemplo. sed 's/ě/\\\[ecaron]/g; s/š/\\\[scaron]/g; .... ou nem mesmo usar dois pontos e apenas colocar cada expressão de substituição em uma nova linha .. o que permite que eles se alinhem perfeitamente ...

informação relacionada