Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have this script that I assign t oa keyboard shortcut to simulate pasting through middle click:

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

I use -text with xvkbd when the text is in Czech (my language) because xvkbd does not understand diacritics like ě but only in form like \[ecaron]. Now, with this option, if there is a newline int xsel, it does not get printed with xvkbd. However, when I do

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

Newlines do get printed.

I suspect the trouble is in the last sed expression sed ':a;N;$!ba;s/\n/\\n/g', but I do not know how to make it better. I think that I need to take care for \ns somehow?

share|improve this question

1 Answer 1

up vote 1 down vote accepted

EDIT: I found the problem, but the rest may still be worth reading for when you actually do want a trailing newline `...

You are missing an extra \\ or even just \

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

MORE INFO: Regarding the issue of $( ) vs backquotes for command substitution, mentioned a comment I put to this question, here is an excerpt from 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.

-- Original Post --

It won't print the last \n but it adds intermediate \n into $xx ...

Here is a simplified version of your last sed call:

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

Output:

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

The reason it doesn't have a final \n (in the above example) is that there simply won't be a trailing newline char in the pattern-space for the lastline (only ones from previous line-endings, via N, will be there)... sed will subsequently output the final newline char as it exits, but even so, it will be gobbled up by the xx=$(command substitution) either by $( ) or backticks ...

To include a final \n, it needs just one final substitution.

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

Or is it a case of you are not getting even the intermediate \ns?


Just a side note: You don't need to have umpteen seds calling that many processes. You can concatenate them via ; (colon), eg. sed 's/ě/\\\[ecaron]/g; s/š/\\\[scaron]/g; .... or not even use the colons and just put each substitution expression on a new line.. which allows them to line up nicely...

share|improve this answer
    
On the side note, it has been pointed to me before I could use sed -e 'bla/bla' -e 'bleble' but the thing about having each expression on a new line is very neat and readable, thanks. Thanks for the answer (even the long one) anyway. One thing I am still unclear on is why I need so many \ ? I mean, with s/\n/\\n/g, I would expect it to catch any newline (\n) and replace it with one backslash (\\ would do that) and then print n. Does sed for some reason think I am trying to escape a newline? –  sup Apr 18 '12 at 18:42
    
I've just found the real(?) problem this time (I hope)... It is to do with backticks vs $( ) ... your \\n works fine with $( ) but loses the newlines otherwise... (but I'm starting to phase out on this one...need sleep occasionally :) ... It works when I use $( ) ... which, by the way, is a much preferred and encouraged (newer) style.. –  Peter.O Apr 18 '12 at 18:50
    
Using \\n (not \\\\n), $( ) works for me, but backticks lose every intermediate newline... There is one more issue though, and that is of having to determine before you process your xsel data whether or not is had a trailing newline, and then selectively add (or not add) that final trailing newline via a sed expression... –  Peter.O Apr 18 '12 at 19:04
    
I will remember $(), thanks for that, it works with just two backslashes now. As for the trailing \n, it seems to be keeping it now, so I will let it be. In case I need to test for it, I just do xsel | grep -qE "/n$ and then act accordingly on $?. –  sup Apr 18 '12 at 23:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.