How to avoid bash command substitution to remove the newline character? -
to speed bash script execution, keep result of command in variable using command substitution, command substitution replaces 0x0a
newline character space. example:
a=`df -h`
or
a=$( df -h )
when want process further $a
, newline characters replaced space , lines on 1 line, harder grep:
echo $a
what easy tricks avoid newline character being removed command substitution?
non-trailing newlines not removed
the newlines looking there, don't see them, because use echo
without quoting variable.
validation:
$ a=$( df -h ) $ echo $a filesystem size used avail use% mounted on /dev/sda3 276g 50g 213g 19% / udev 2.1g 4.1k 2.1g 1% /dev tmpfs 832m 820k 832m 1% /run none 5.3m 0 5.3m 0% /run/lock none 2.1g 320k 2.1g 1% /run/shm $ echo "$a" filesystem size used avail use% mounted on /dev/sda3 276g 50g 213g 19% / udev 2.1g 4.1k 2.1g 1% /dev tmpfs 832m 820k 832m 1% /run none 5.3m 0 5.3m 0% /run/lock none 2.1g 320k 2.1g 1% /run/shm $
trailing newlines removed
as @user4815162342 correctly pointed out, although newlines within output not removed, trailing newlines removed command substitution. see experiment below:
$ a=$'test\n\n' $ echo "$a" test $ b=$(echo "$a") $ echo "$b" test $
in cases not matter, because echo
add removed newline (unless invoked -n
option), there edge cases there more 1 trailing newlines in output of program, , significant reason.
workarounds
1. add dummy character
in these case, @scrutinizer mentioned, can use following workaround:
$ a=$(printf 'test\n\n'; printf x); a=${a%x} $ echo "$a" test $
explanation: character x
added output (using printf x
), after newlines. since newlines not trailing more, not removed command substitution. next step remove x
added, using %
operator in ${a%x}
. have original output, newlines present!!!
2. read using process substitution
instead of using command substitution assign output of program variable, can instead use process substitution feed output of program read
built-in command (credit @ormaaj). process substitution preserves newlines. reading output variable bit tricky, can this:
$ ifs= read -rd '' var < <( printf 'test\n\n' ) $ echo "$var" test $
explanation:
- we set internal field separator read command null,
ifs=
. otherwiseread
not assign entire outputvar
, first token. - we invoke
read
options-rd ''
.r
preventing backslash act special character, ,d ''
set delimiter nothing, read reads entire output, instead of first line.
3. read pipe
instead of using command or process substitution assign output of program variable, can instead pipe output of program read
command (credit @ormaaj). piping preserves newlines. note however, time set lastpipe
shell optional behavior, using the shopt
builtin. required, read
command executed in current shell environment. otherwise, variable assigned in subshell, , not accessible rest of script.
$ cat test.sh #!/bin/bash shopt -s lastpipe printf "test\n\n" | ifs= read -rd '' var echo "$var" $ ./test.sh test $
Comments
Post a Comment