Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use bash substitution to append a newline at the end of each element of a list

Tags:

bash

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.

like image 683
Philippe A. Avatar asked Dec 08 '14 16:12

Philippe A.


2 Answers

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" ...
like image 118
anubhava Avatar answered Oct 19 '22 20:10

anubhava


printf would have been my answer as well. Another technique is to use IFS:

$ IFS=$'\n'
$ list="$*"
$ echo "$list"
arg1
arg2
arg3

Notes:

  • uses ANSI-C quoting for the newline sequence
  • "$*" (with the quotes, crucial) joins the positional params using the first char of $IFS
  • quote the shell variable for the echo command to preserve the inner newlines.

That 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 "$*" )
like image 43
glenn jackman Avatar answered Oct 19 '22 18:10

glenn jackman