1

Given a list of arguments, I am trying to produce a string looks like the following using bash script:

 - arg_1
 - arg_2
 - arg_3
 - arg_4

And here is my script trying to do this:

seeds=
for i in $*; do
  seeds=`printf "$seeds    - $i\n"`
done;
echo "$seeds"

However, when I run it with input arg_1 arg_2 arg_3 arg_4, the above script generates the following output, which apparently ignores my spacing and new-line character:

- arg_1 - arg_2 - arg_3 - arg_4

Can I know what did I do wrong in my script? or is there a better way to do this?

keelar
  • 5,814
  • 7
  • 40
  • 79

3 Answers3

5

Quoting and whitespace is very important in the shell:

#!/usr/bin/env bash

for arg in "$@"; do
    seed="$seed    - $arg\n"
done
echo -ne "$seed"

Demo:

$ ./script.sh arg_1 arg_2 arg_3 arg_4
    - arg_1
    - arg_2
    - arg_3
    - arg_4
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
  • In addition, I am not trying to print them, but more importantly storing them in a string since I will later invoke `sed` to use them to modify a file. – keelar Aug 02 '13 at 20:05
  • 1
    @keelar http://stackoverflow.com/questions/12314451/accessing-bash-command-line-args-vs – Chris Seymour Aug 02 '13 at 20:07
3

Like sudo_O says (and ShellCheck would have pointed out), you should use "$@" rather than $* for the minimal fix.

You asked if there was a better way of doing it, though, and there definitely is. When given more arguments than necessary to fulfill the format string, printf will repeat the output as necessary. This lets us simply write:

printf "- %s\n" "$@" 
that other guy
  • 116,971
  • 11
  • 170
  • 194
  • +1 for SpellCheck however check the OP comments on my answer `I am not trying to print them, but more importantly storing them in a string`. – Chris Seymour Aug 02 '13 at 20:42
  • @sudo_O: That's easily changed: `seeds=$(printf "- %s\n" "$@" )` (although note that the final linefeed will be trimmed before it's stored in the variable -- if this is a problem, there are solutions but a bit messy). – Gordon Davisson Aug 02 '13 at 22:32
1

I think your script is too complex. I don't think you need command substitution here. May you try this one

seeds=
for i in $*; do
  seeds="$seeds\n- $i"
done;
echo -e ${seeds#\\n}
user1146332
  • 2,630
  • 1
  • 15
  • 19
  • Thank you, it seems work except it introduces one additional new line at the beginning (although it's easy to fix that). – keelar Aug 02 '13 at 20:02
  • I changed it according to your needs – user1146332 Aug 02 '13 at 20:07
  • no only the first one. From bash's reference manual: `If the pattern matches the beginning of the expanded value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern deleted` – user1146332 Aug 02 '13 at 20:11