1

I need to delete the formatting in the text contained in the clipboard, but keeping some elements. The most important are the "new line" characters. In a simple script, the effect of

variable=$(xsel --clipboard)

is that the text appears to be all in the same line, so it has lost all the "new line" characters.

1) Is there a way to avoid this? Sometimes I copy text from Windows format (so the newline is "\r\n") and sometimes from *nix (and so the newline is just "\n").

2) The previous question was the most important, but: there is also a way to preserve the "bold", "italic" and "underlined" formatting elements? Because they are all lost too with that shell command.

Thank you anyway!

BowPark
  • 4,895

1 Answers1

2

Yes. command substitution removes every trailing newline1.

To work around it:

var=$(xsel --clipboard; echo .)
var=${var%?}

That is add .\n to that output. And remove the dot afterwards with ${var%?} (the \n is taken care of by the command substitution).

Note that except with zsh, shell variables can't contain NUL bytes.

If you want to preserve the exit status:

var=$(xsel --clipboard; ret=$?; echo .; exit "$ret")
ret=$?
var=${var%?}

Remember to quote $var when expanding it:

printf %s "$var"

A helper function:

cmdsubst() {
  _var=$1; shift
  eval "$_var="'$("$@"; ret=$?; echo .; exit "$ret")
    _ret=$?
    '"$_var=\${$_var%?}"
  return "$_ret"
}

To be used as:

cmdsubst var xsel --clipboard

To preserve the "bold"... Some tools export the CLIPBOARD selection as text/html in addition to just a UTF8 string. In that case (with recent versions of xclip), you can do:

cmdsubst html xclip -sel c -o -t text/html

See the output of xclip -sel c -o -t TARGETS to see what selection targets the current owner of the CLIPBOARD selection provides.

Example after copying a part of my comment to Mikel above in iceweasel:

$ xclip -sel c -o -t TARGETS
TIMESTAMP
TARGETS
MULTIPLE
SAVE_TARGETS
text/html
text/_moz_htmlcontext
text/_moz_htmlinfo
UTF8_STRING
COMPOUND_TEXT
TEXT
STRING
text/x-moz-url-priv
$ xclip -sel c -o -t text/html
<span class="comment-copy"><i>should</i> remove <i>only one</i> trailing newline</span>
$ xclip -sel c -o -t TEXT
should remove only one trailing newline

1 An exception to that are the shells of the rc family where you can say you don't want any post-processing with the var = ``(){xsel --clipboard} syntax.

  • Thank you for your detailed answer. Forgive me for the unexperience, but your code doesn't work in my shell (bash). I mean that `var=$(xsel --clipboard; echo .) var=${var%?}' prints again the string without the new lines. With the xclip example, I don't obtain an output so clear like the yours, it's like for each word of your comment it included in the tags parts of the stylesheet, and so it result unreadable. Maybe it's the browser? – BowPark Mar 21 '14 at 16:04
  • Are you sure you don't get the newline? Did you do printf %s "$var" | od -tc for instance to verify what $var contains? – Stéphane Chazelas Mar 21 '14 at 16:05
  • Now I retried and it works! And with 'od -tc' it shows the "\n" character. – BowPark Mar 21 '14 at 16:11
  • what is the effect of 'echo .'? – BowPark Mar 21 '14 at 16:14
  • @BowPark It adds a non-newline character followed by a newline; the command substitution removes the trailing newline, and ${$_var%?} below removes the dot. This way the variable ends up containing the exact output of the command including trailing newlines. – Gilles 'SO- stop being evil' Mar 21 '14 at 22:39