6

How can I store $@ in a variable while keeping its properties?

I want to obtain exactly the same behavior even if I use $@ or my own variable in all possible situations.

The attempts below didn't work:

args=$@
args2="$@"        # the arguments are combined (see the last output paragraph)

I tested them using the following line:

s.sh A B="       " C

s.sh

#!/bin/bash

args=$@
args2="$@"
#args3 = ? - TODO

echo $args
echo $args2
echo $@
#echo $args3   

echo

echo "$args"
echo "$args2"
echo "$@"
#echo "$args3"

echo

java A $args
java A $args2
java A $@
#java A $args3

echo

java A "$args"
java A "$args2"
java A "$@"
#java A "$args3"

A.java

import java.util.Arrays;

public class A {
    public static void main(String args[]){
        System.out.println(args.length + ": " + Arrays.asList(args));
    }
}

Actual output:

A B= C
A B= C
A B= C

A B= C
A B=        C
A B=        C

3: [A, B=, C]
3: [A, B=, C]
3: [A, B=, C]

1: [A B= C]
1: [A B=        C]
3: [A, B=       , C]

Expected output (if TODO is replaced by a solution) and echos are enabled

A B= C
A B= C
A B= C
A B= C

A B= C
A B=        C
A B=        C
A B=        C

3: [A, B=, C]
3: [A, B=, C]
3: [A, B=, C]
3: [A, B=, C]

1: [A B= C]
1: [A B=        C]
3: [A, B=       , C]
3: [A, B=       , C]
Jahid
  • 21,542
  • 10
  • 90
  • 108
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199

2 Answers2

7

You can store it in an array:

args=("$@")

then you can access each of the arguments with index: "${args[index]}" and all arguments at once with "${args[@]}".

Jahid
  • 21,542
  • 10
  • 90
  • 108
  • 4
    You should use double-quotes when accessing the array elements (e.g. `"${args[index]}"`). Also, you can get all arguments back at once with `"${args[@]}"`. – Gordon Davisson May 25 '15 at 17:23
6

It depends what you want to do. Using $@ keeps the command-line arguments separated, if you want to join them together as a single string then use $* instead. For example:

args="$*"
java A $args

When "$*" is used then the command-line arguments are joined into one string using the first character of IFS as the "glue" between each argument. By default that is a space. The only issue with this is if any of the arguments themselves contain whitespace. If you know that spaces are going to be used, not tabs, then you can mess with IFS:

oldIFS="$IFS"
IFS=$'\t'
args="$*"
java A.py $args

IFS="$oldIFS"

Edit: since you wish to keep them separate, then use an array:

args=("$@")
java A "${args[@]}"

Using an "index" of @ has a similar effect to "$@" (you can also use * to join elements together, just like "$*").

cdarke
  • 42,728
  • 8
  • 80
  • 84
  • I want to keep the arguments separated as they are in `$@`. But I want to have my own variable for this. So, supposing that I have a "4th" good line in every output group, it has to be identical with the 3rd line. – ROMANIA_engineer May 25 '15 at 13:55
  • @helpYou: sorry, I don't understand what you mean by an output group. I suggest you edit your question to show the output you desire as well as the output that you get. – cdarke May 25 '15 at 14:03
  • `args=$*` behaves the same as `args="$*"`; no word-splitting or pathname generation is applied on the right-hand side of an assignment. – chepner May 25 '15 at 15:55
  • @chepner: yes, you are correct, I was mixing the behaviour of `$@`. I'll edit. – cdarke May 25 '15 at 16:06