I am looking for a bash one liner that appends a newline after each element of a list. If I call the script as:
./script arg1 arg2 arg3
I want the output to be
arg1
arg2
arg3
I tried different variations of the following. The newline does not get added. Any ordinary char gets added.
# pretty much works except for an extra space
list=${@/%/x}
echo "$list"
# appends 'n'
list=${@/%/\n}
echo "$list"
# appends nothing
list=${@/%/$'\n'}
echo "$list"
# appends nothing, \x078 would append 'x'
list=${@/%/$'\x0D'}
echo "$list"
# appends nothing
CR=$'\n'
list=${@/%/$CR}
echo "$list"
# same issues with arrays
tmp=($@)
list=${tmp/%/\n}
echo "$list"
What fix or alternative do you suggest? I obviously could write a loop or call tr but that's precisely what I thought I could avoid with a bash substitution.
You can use this function with "$@"
:
f() { printf "%s\n" "$@"; }
f arg1 arg2 arg3
arg1
arg2
arg3
As per man bash
@ Expands to the positional parameters, starting from one. When the expansion occurs
within double quotes, each parameter expands to a separate word. That is, "$@" is
equivalent to "$1" "$2" ...
printf would have been my answer as well. Another technique is to use IFS
:
$ IFS=$'\n'
$ list="$*"
$ echo "$list"
arg1
arg2
arg3
Notes:
"$*"
(with the quotes, crucial) joins the positional params using the first char of $IFSThat redefines the IFS value for the current shell. You can save the old value first and restore it after:
oldIFS=$IFS; IFS=$'\n'; list="$*"; IFS=$oldIFS
or you can use a subshell so the modification is discarded for you:
$ list=$( IFS=$'\n'; echo "$*" )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With