Bash - How to force literal in subshell string? - bash

I'd like to control variable expansion when executing a shell command using sudo bash -c.
I know I can do it from a normal shell:
bash$ export FOO=foo
bash$ export BAR=bar
bash$ echo "expand $FOO but not "'$BAR'""
expand foo but not $BAR
How can I do the above using sudo bash -c?
bash$ sudo bash -c "echo "expand $FOO but not "'$BAR'"""
expand
bash$ sudo bash -c 'echo "expand $FOO but not "'$BAR'""'
expand but not bar

You can use this with escaped $ that you don't want to expand:
$> bash -c "echo \"expand $FOO but not \"'\$BAR'"
expand foo but not $BAR
However I recommend using here-doc to avoid escaping:
# original echo replaced with printf
$> printf 'expand %s but not %s\n' "$FOO" '$BAR'
expand foo but not $BAR
# prints in here-doc with bash
$> bash<<-'EOF'
printf 'expand %s but not %s\n' "$FOO" '$BAR'
EOF
expand foo but not $BAR

Pass arguments rather than trying to generate a string to pass to bash.
$ bash -c 'echo "expand $1 but not $2"' _ "$FOO" '$BAR'
expand 5 but not $BAR
(The _ is just a dummy value to set $0 in the script specified by -c.)

Related

Passing arguments between a script and a binary [duplicate]

I am writing a very simple script that calls another script, and I need to propagate the parameters from my current script to the script I am executing.
For instance, my script name is foo.sh and calls bar.sh.
foo.sh:
bar $1 $2 $3 $4
How can I do this without explicitly specifying each parameter?
Use "$#" instead of plain $# if you actually wish your parameters to be passed the same.
Observe:
$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $#
$ cat quotes.sh
#!/bin/bash
echo_args.sh "$#"
$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
For bash and other Bourne-like shells:
bar "$#"
Use "$#" (works for all POSIX compatibles).
[...] , bash features the "$#" variable, which expands to all command-line parameters separated by spaces.
From Bash by example.
I realize this has been well answered but here's a comparison between "$#" $# "$*" and $*
Contents of test script:
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$#"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $#; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
Now, run the test script with various arguments:
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
A lot answers here recommends $# or $* with and without quotes, however none seems to explain what these really do and why you should that way. So let me steal this excellent summary from this answer:
+--------+---------------------------+
| Syntax | Effective result |
+--------+---------------------------+
| $* | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| $# | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| "$*" | "$1c$2c$3c...c${N}" |
+--------+---------------------------+
| "$#" | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+
Notice that quotes makes all the difference and without them both have identical behavior.
For my purpose, I needed to pass parameters from one script to another as-is and for that the best option is:
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
Notice no quotes and $# should work as well in above situation.
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
Just thought this may be a bit more useful when trying to test how args come into your script
If you include $# in a quoted string with other characters the behavior is very odd when there are multiple arguments, only the first argument is included inside the quotes.
Example:
#!/bin/bash
set -x
bash -c "true foo $#"
Yields:
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
But assigning to a different variable first:
#!/bin/bash
set -x
args="$#"
bash -c "true foo $args"
Yields:
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
My SUN Unix has a lot of limitations, even "$#" was not interpreted as desired. My workaround is ${#}. For example,
#!/bin/ksh
find ./ -type f | xargs grep "${#}"
By the way, I had to have this particular script because my Unix also does not support grep -r
Sometimes you want to pass all your arguments, but preceded by a flag (e.g. --flag)
$ bar --flag "$1" --flag "$2" --flag "$3"
You can do this in the following way:
$ bar $(printf -- ' --flag "%s"' "$#")
note: to avoid extra field splitting, you must quote %s and $#, and to avoid having a single string, you cannot quote the subshell of printf.
bar "$#" will be equivalent to bar "$1" "$2" "$3" "$4"
Notice that the quotation marks are important!
"$#", $#, "$*" or $* will each behave slightly different regarding escaping and concatenation as described in this stackoverflow answer.
One closely related use case is passing all given arguments inside an argument like this:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\"".
I use a variation of #kvantour's answer to achieve this:
bash -c "bar $(printf -- '"%s" ' "$#")"
Works fine, except if you have spaces or escaped characters. I don't find the way to capture arguments in this case and send to a ssh inside of script.
This could be useful but is so ugly
_command_opts=$( echo "$#" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&#",$i) ; gsub(/ $/,"",$i );gsub (/$/,"#",$i) }; print $0 }' | tr '#' \' )
"${array[#]}" is the right way for passing any array in bash. I want to provide a full cheat sheet: how to prepare arguments, bypass and process them.
pre.sh -> foo.sh -> bar.sh.
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[#]}"
#!/bin/bash
./bar.sh "$#"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
result:
--a=b c
--e=f g
--q=w e
--a=s "'d'"

Take file as an input and run awk command on it [duplicate]

I am writing a very simple script that calls another script, and I need to propagate the parameters from my current script to the script I am executing.
For instance, my script name is foo.sh and calls bar.sh.
foo.sh:
bar $1 $2 $3 $4
How can I do this without explicitly specifying each parameter?
Use "$#" instead of plain $# if you actually wish your parameters to be passed the same.
Observe:
$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $#
$ cat quotes.sh
#!/bin/bash
echo_args.sh "$#"
$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
For bash and other Bourne-like shells:
bar "$#"
Use "$#" (works for all POSIX compatibles).
[...] , bash features the "$#" variable, which expands to all command-line parameters separated by spaces.
From Bash by example.
I realize this has been well answered but here's a comparison between "$#" $# "$*" and $*
Contents of test script:
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$#"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $#; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
Now, run the test script with various arguments:
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
A lot answers here recommends $# or $* with and without quotes, however none seems to explain what these really do and why you should that way. So let me steal this excellent summary from this answer:
+--------+---------------------------+
| Syntax | Effective result |
+--------+---------------------------+
| $* | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| $# | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| "$*" | "$1c$2c$3c...c${N}" |
+--------+---------------------------+
| "$#" | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+
Notice that quotes makes all the difference and without them both have identical behavior.
For my purpose, I needed to pass parameters from one script to another as-is and for that the best option is:
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
Notice no quotes and $# should work as well in above situation.
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
Just thought this may be a bit more useful when trying to test how args come into your script
If you include $# in a quoted string with other characters the behavior is very odd when there are multiple arguments, only the first argument is included inside the quotes.
Example:
#!/bin/bash
set -x
bash -c "true foo $#"
Yields:
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
But assigning to a different variable first:
#!/bin/bash
set -x
args="$#"
bash -c "true foo $args"
Yields:
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
My SUN Unix has a lot of limitations, even "$#" was not interpreted as desired. My workaround is ${#}. For example,
#!/bin/ksh
find ./ -type f | xargs grep "${#}"
By the way, I had to have this particular script because my Unix also does not support grep -r
Sometimes you want to pass all your arguments, but preceded by a flag (e.g. --flag)
$ bar --flag "$1" --flag "$2" --flag "$3"
You can do this in the following way:
$ bar $(printf -- ' --flag "%s"' "$#")
note: to avoid extra field splitting, you must quote %s and $#, and to avoid having a single string, you cannot quote the subshell of printf.
bar "$#" will be equivalent to bar "$1" "$2" "$3" "$4"
Notice that the quotation marks are important!
"$#", $#, "$*" or $* will each behave slightly different regarding escaping and concatenation as described in this stackoverflow answer.
One closely related use case is passing all given arguments inside an argument like this:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\"".
I use a variation of #kvantour's answer to achieve this:
bash -c "bar $(printf -- '"%s" ' "$#")"
Works fine, except if you have spaces or escaped characters. I don't find the way to capture arguments in this case and send to a ssh inside of script.
This could be useful but is so ugly
_command_opts=$( echo "$#" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&#",$i) ; gsub(/ $/,"",$i );gsub (/$/,"#",$i) }; print $0 }' | tr '#' \' )
"${array[#]}" is the right way for passing any array in bash. I want to provide a full cheat sheet: how to prepare arguments, bypass and process them.
pre.sh -> foo.sh -> bar.sh.
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[#]}"
#!/bin/bash
./bar.sh "$#"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
result:
--a=b c
--e=f g
--q=w e
--a=s "'d'"

Using <<< throws error on sh shell not in bash

In Sh
[SunOs] /opt # sh
[\h] \w \$ read -a array <<< "1 2 3";echo ${array[1]}
syntax error: `<' unexpected
In Bash
[SunOs] ~ # bash
[SunOs] ~ # read -a array <<< "1 2 3";echo ${array[1]}
2
Why the Error thorwn in "sh" shell, i'm using SunOS 5.10 Generic_147440-10 sun4v sparc sun4v
Herestrings aren't supported in sh.
This causes the error when you try to run it using sh.
As a workaround you may use the builtin POSIX command set to assign your arguments to the positional parameters $1, $2, ... or the positional parameter array $# respectively
{
IFS="`printf ' \n\t'`"
export IFS
printf '%s' "$IFS" | od -b
set -- `printf '%s' "1 2 3"`
echo "$0"
echo "$1"
echo "$2"
echo "$3"
echo "$#"
}

Propagate all arguments in a Bash shell script

I am writing a very simple script that calls another script, and I need to propagate the parameters from my current script to the script I am executing.
For instance, my script name is foo.sh and calls bar.sh.
foo.sh:
bar $1 $2 $3 $4
How can I do this without explicitly specifying each parameter?
Use "$#" instead of plain $# if you actually wish your parameters to be passed the same.
Observe:
$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $#
$ cat quotes.sh
#!/bin/bash
echo_args.sh "$#"
$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
For bash and other Bourne-like shells:
bar "$#"
Use "$#" (works for all POSIX compatibles).
[...] , bash features the "$#" variable, which expands to all command-line parameters separated by spaces.
From Bash by example.
I realize this has been well answered but here's a comparison between "$#" $# "$*" and $*
Contents of test script:
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$#"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $#; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
Now, run the test script with various arguments:
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
A lot answers here recommends $# or $* with and without quotes, however none seems to explain what these really do and why you should that way. So let me steal this excellent summary from this answer:
+--------+---------------------------+
| Syntax | Effective result |
+--------+---------------------------+
| $* | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| $# | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| "$*" | "$1c$2c$3c...c${N}" |
+--------+---------------------------+
| "$#" | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+
Notice that quotes makes all the difference and without them both have identical behavior.
For my purpose, I needed to pass parameters from one script to another as-is and for that the best option is:
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
Notice no quotes and $# should work as well in above situation.
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
Just thought this may be a bit more useful when trying to test how args come into your script
If you include $# in a quoted string with other characters the behavior is very odd when there are multiple arguments, only the first argument is included inside the quotes.
Example:
#!/bin/bash
set -x
bash -c "true foo $#"
Yields:
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
But assigning to a different variable first:
#!/bin/bash
set -x
args="$#"
bash -c "true foo $args"
Yields:
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
My SUN Unix has a lot of limitations, even "$#" was not interpreted as desired. My workaround is ${#}. For example,
#!/bin/ksh
find ./ -type f | xargs grep "${#}"
By the way, I had to have this particular script because my Unix also does not support grep -r
Sometimes you want to pass all your arguments, but preceded by a flag (e.g. --flag)
$ bar --flag "$1" --flag "$2" --flag "$3"
You can do this in the following way:
$ bar $(printf -- ' --flag "%s"' "$#")
note: to avoid extra field splitting, you must quote %s and $#, and to avoid having a single string, you cannot quote the subshell of printf.
bar "$#" will be equivalent to bar "$1" "$2" "$3" "$4"
Notice that the quotation marks are important!
"$#", $#, "$*" or $* will each behave slightly different regarding escaping and concatenation as described in this stackoverflow answer.
One closely related use case is passing all given arguments inside an argument like this:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\"".
I use a variation of #kvantour's answer to achieve this:
bash -c "bar $(printf -- '"%s" ' "$#")"
Works fine, except if you have spaces or escaped characters. I don't find the way to capture arguments in this case and send to a ssh inside of script.
This could be useful but is so ugly
_command_opts=$( echo "$#" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&#",$i) ; gsub(/ $/,"",$i );gsub (/$/,"#",$i) }; print $0 }' | tr '#' \' )
"${array[#]}" is the right way for passing any array in bash. I want to provide a full cheat sheet: how to prepare arguments, bypass and process them.
pre.sh -> foo.sh -> bar.sh.
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[#]}"
#!/bin/bash
./bar.sh "$#"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
result:
--a=b c
--e=f g
--q=w e
--a=s "'d'"

Pass ALL Arguments from Bash Script to Another Command [duplicate]

I am writing a very simple script that calls another script, and I need to propagate the parameters from my current script to the script I am executing.
For instance, my script name is foo.sh and calls bar.sh.
foo.sh:
bar $1 $2 $3 $4
How can I do this without explicitly specifying each parameter?
Use "$#" instead of plain $# if you actually wish your parameters to be passed the same.
Observe:
$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $#
$ cat quotes.sh
#!/bin/bash
echo_args.sh "$#"
$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
For bash and other Bourne-like shells:
bar "$#"
Use "$#" (works for all POSIX compatibles).
[...] , bash features the "$#" variable, which expands to all command-line parameters separated by spaces.
From Bash by example.
I realize this has been well answered but here's a comparison between "$#" $# "$*" and $*
Contents of test script:
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$#"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $#; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
Now, run the test script with various arguments:
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
A lot answers here recommends $# or $* with and without quotes, however none seems to explain what these really do and why you should that way. So let me steal this excellent summary from this answer:
+--------+---------------------------+
| Syntax | Effective result |
+--------+---------------------------+
| $* | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| $# | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| "$*" | "$1c$2c$3c...c${N}" |
+--------+---------------------------+
| "$#" | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+
Notice that quotes makes all the difference and without them both have identical behavior.
For my purpose, I needed to pass parameters from one script to another as-is and for that the best option is:
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
Notice no quotes and $# should work as well in above situation.
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
Just thought this may be a bit more useful when trying to test how args come into your script
If you include $# in a quoted string with other characters the behavior is very odd when there are multiple arguments, only the first argument is included inside the quotes.
Example:
#!/bin/bash
set -x
bash -c "true foo $#"
Yields:
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
But assigning to a different variable first:
#!/bin/bash
set -x
args="$#"
bash -c "true foo $args"
Yields:
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
My SUN Unix has a lot of limitations, even "$#" was not interpreted as desired. My workaround is ${#}. For example,
#!/bin/ksh
find ./ -type f | xargs grep "${#}"
By the way, I had to have this particular script because my Unix also does not support grep -r
Sometimes you want to pass all your arguments, but preceded by a flag (e.g. --flag)
$ bar --flag "$1" --flag "$2" --flag "$3"
You can do this in the following way:
$ bar $(printf -- ' --flag "%s"' "$#")
note: to avoid extra field splitting, you must quote %s and $#, and to avoid having a single string, you cannot quote the subshell of printf.
bar "$#" will be equivalent to bar "$1" "$2" "$3" "$4"
Notice that the quotation marks are important!
"$#", $#, "$*" or $* will each behave slightly different regarding escaping and concatenation as described in this stackoverflow answer.
One closely related use case is passing all given arguments inside an argument like this:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\"".
I use a variation of #kvantour's answer to achieve this:
bash -c "bar $(printf -- '"%s" ' "$#")"
Works fine, except if you have spaces or escaped characters. I don't find the way to capture arguments in this case and send to a ssh inside of script.
This could be useful but is so ugly
_command_opts=$( echo "$#" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&#",$i) ; gsub(/ $/,"",$i );gsub (/$/,"#",$i) }; print $0 }' | tr '#' \' )
"${array[#]}" is the right way for passing any array in bash. I want to provide a full cheat sheet: how to prepare arguments, bypass and process them.
pre.sh -> foo.sh -> bar.sh.
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[#]}"
#!/bin/bash
./bar.sh "$#"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
result:
--a=b c
--e=f g
--q=w e
--a=s "'d'"

Resources