Rich’s sh (POSIX shell) tricks; the ‘\n’ character, string in a shell-quoted form, and more

While www link diving I found this great single page which mayn’t solve a community discussion problem on the shell removing the ‘\n’ character.

Rich’s sh (POSIX shell) tricks https://www.etalabs.net/sh_tricks.html

Sections (and more):

  • Getting non-clobbered output from command substitution
  • Returning strings from a shell function
  • Shell-quoting arbitrary strings

kakoune editor:

:fifo man man<ret>
*fifo*[scratch]
No manual entry for man=its_a_newline_character\n
-----------------------------------------------^^-

kakoune demo code:

# ref: https://github.com/mawww/config/blob/master/kakrc#L136
define-command -docstring "shell command stdout to fifo buffer" -params .. fifo %{ evaluate-commands %sh{
  if ! output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-fifo.XXXXXXXX)/fifo; then printf "mktemp fifo failed, now exiting...\n"; exit 1; fi
  mkfifo ${output}

  # LOOK HERE FOR RICH'S TRICK
  foo='its_a_newline_character\n'
  dest="$@"
  ( eval "$dest=\$foo" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null

  printf %s\\n "evaluate-commands -try-client '$kak_opt_toolsclient' %{
    edit! -fifo ${output} *fifo*
    hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }
  }"
}}


Same guy, same page:

Sometimes it’s necessary to put a string in a shell-quoted form, for instance if it needs to be expanded into a command that will be evaluated with eval.

quote () { printf %s\\n "$1" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/" ; }

This function simply replaces every instance of «’» (single quote) within the string with «’\’’» (single quote, backslash, single quote, single quote), then puts single quotes at the beginning and end of the string.

Since the only character whose meaning is special within single quotes is the single quote character itself, this is totally safe. Trailing newlines are handled correctly, and the single quote at the end doubles as a safety character to prevent command substitution from clobbering the trailing newlines, should one want to do something like:

quoted=$(quote "$var")

If nothing more it’s a good page of tricks. Bye :wave:

1 Like