8

I would like to concatenate all the arguments passed to my bash script except the flag.

So for example, If the script takes inputs as follows:

./myBashScript.sh -flag1 exampleString1 exampleString2

I want the result to be "exampleString1_exampleString2"

I can do this for a predefined number of inputs (i.e. 2), but how can i do it for an arbitrary number of inputs?

zpesk
  • 4,343
  • 7
  • 39
  • 61

6 Answers6

14
function concatenate_args
{
    string=""
    for a in "$@" # Loop over arguments
    do
        if [[ "${a:0:1}" != "-" ]] # Ignore flags (first character is -)
        then
            if [[ "$string" != "" ]]
            then
                string+="_" # Delimeter
            fi
            string+="$a"
        fi
    done
    echo "$string"
}

# Usage:
args="$(concatenate_args "$@")"
Tyilo
  • 28,998
  • 40
  • 113
  • 198
  • Sorry to be strict, but -1 for bad shell style (very verbose and `[[ ... ]]` isn't portable). Use `test` instead, and see my solution for an alternative to using `${a:0:1}` – Jo So Feb 20 '12 at 01:39
  • @JoSo Why isn't `[[ ]]` portable? – Tyilo Feb 20 '12 at 14:09
  • It's bash, not POSIX sh. (The same with `${a:0:1}`). While there are some who don't care because bash is installed on nearly any system, in this case really it has no use (use `test` alias `[ ... ]` instead). – Jo So Feb 20 '12 at 15:53
  • 3
    @JoSo he clearly says that he is using bash. – Tyilo Feb 20 '12 at 16:11
  • I didn't say it doesn't work, it's just a matter of style (and portability). We should give examples of good coding practices and yours isn't one. – Jo So Feb 20 '12 at 18:55
3

You can also use formatted strings to concatenate args.

# assuming flag is first arg and optional
flag=$1
[[ $1 = ${1#-} ]] && unset $flag || shift

concat=$(printf '%s_' ${@})
echo ${concat%_} # to remove the trailing _

nJoy!

nickl-
  • 8,417
  • 4
  • 42
  • 56
3

This is an ugly but simple solution:

echo $* | sed -e "s/ /_/g;s/[^_]*_//"
mvds
  • 45,755
  • 8
  • 102
  • 111
2

Here's a piece of code that I'm actually proud of (it is very shell-style I think)

#!/bin/sh

firsttime=yes
for i in "$@" 
do
    test "$firsttime" && set -- && unset firsttime
    test "${i%%-*}" && set -- "$@" "$i"
done

IFS=_ ; echo "$*"

I've interpreted your question so as to remove all arguments beginning with -

If you only want to remove the beginning sequence of arguments beginnnig with -:

#!/bin/sh

while ! test "${1%%-*}"
do
    shift
done

IFS=_ ; echo "$*"

If you simply want to remove the first argument:

#!/bin/sh

shift
IFS=_ ; printf %s\\n "$*"
Jo So
  • 25,005
  • 6
  • 42
  • 59
1
flag="$1"
shift
oldIFS="$IFS"
IFS="_"
the_rest="$*"
IFS="$oldIFS"

In this context, "$*" is exactly what you're looking for, it seems. It is seldom the correct choice, but here's a case where it really is the correct choice.

Alternatively, simply loop and concatenate:

flag="$1"
shift
the_rest=""
pad=""
for arg in "$@"
do
    the_rest="${the_rest}${pad}${arg}"
    pad="_"
done

The $pad variable ensures that you don't end up with a stray underscore at the start of $the_rest.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0
#!/bin/bash
paramCat () {
for s in "$@" 
do
    case $s in 
        -*)
            ;;
        *) 
            echo -n _${s}
            ;; 
    esac
done
}

catted="$(paramCat "$@")"
echo ${catted/_/} 
user unknown
  • 35,537
  • 11
  • 75
  • 121