How to Pass a Complete Argument List in Bash While Keeping Mulitword Arguments Together

How can I pass a complete argument list in bash while keeping mulitword arguments together?

You can use:

eval decho $args

How do I assign a string with multiple flags to a variable reusable in commands?

if ...; then
COMMAND_PREFIX=(gcloud pubsub subscriptions create mysub)
else
COMMAND_PREFIX=(gcloud pubsub subscriptions update mysub)
fi

COMMAND=(
"${COMMAND_PREFIX[@]}"
"--push-endpoint=$SUBSCRIPTION_ENDPOINT"
"--ack-deadline=$ACK_DEADLINE"
"--max-delivery-attempts=$MAX_DELIVERY_ATTEMPTS"
"--dead-letter-topic=$DEADLETTER_TOPIC"
"--min-retry-delay=$MIN_RETRY"
"--max-retry-delay=$MAX_RETRY")

"${COMMAND[@]}"

How to substitute quoted, multi-word strings as arguments?

Don't use quotes, use an array (see BashFAQ #050):

$ myArgs=("hello" "world" "multiword arg with * ?")
+ myArgs=("hello" "world" "multiword arg with * ?")
$ echo "${myArgs[@]}"
+ echo hello world 'multiword arg with * ?'
hello world multiword arg with * ?

If it really needs to be in the form of quoted strings within a string, you're either going to have to use something like eval "echo $myArg" (which can cause some really nasty bugs, if you aren't careful) or parse it yourself (which is going to be difficult).

Passing arguments containing spaces from one script to another in Perl

That whole double-quoted string that is passed to system is first evaluated and thus all variables are interpolated -- so the intended multi-word arguments become merely words in a list. So in the end the string has a command to run with individual words as arguments.

Then, even if you figure out how to stick which quotes in there just right, so to keep those multi-word arguments "together," there's still a chance of a shell being invoked, in which case those arguments again get broken up into words before being passed to the program.

Instead of all this use the LIST form of system. The first argument is then the name of the program that will be directly executed without a shell (see docs for some details on that), and the remaining arguments are passed as they are to that program.

parent

use warnings;
use strict;
use feature 'say';

my @args = ('first words', 'another', 'two more', 'final');

my $prog = 'print_args.pl';

system($prog, @args) == 0
or die "Error w/ system($prog, @args): $!";

and the invoked print_args.pl

use warnings;
use strict;
use feature 'say';

say for @ARGV;

The @ARGV contains arguments passed to the program at invocation. There's more that can be done to inspect the error, see docs and links in them.

By what you show you indeed don't need a shell and the LIST form is generally easy to recommend as a basic way to use system, when the shell isn't needed. If you were to need shell's capabilities for something in that command then you'd have to figure out how to protect those spaces.


And then there are modules for running external programs that are far better than system & Co. From ease-of-use to features and power:
IPC::System::Simple, Capture::Tiny, IPC::Run3, IPC::Run.

How to access command line arguments of the caller inside a function?

My reading of the Bash Reference Manual says this stuff is captured in BASH_ARGV,
although it talks about "the stack" a lot.

#!/bin/bash

shopt -s extdebug

function argv {
for a in ${BASH_ARGV[*]} ; do
echo -n "$a "
done
echo
}

function f {
echo f $1 $2 $3
echo -n f ; argv
}

function g {
echo g $1 $2 $3
echo -n g; argv
f
}

f boo bar baz
g goo gar gaz

Save in f.sh

$ ./f.sh arg0 arg1 arg2
f boo bar baz
fbaz bar boo arg2 arg1 arg0
g goo gar gaz
ggaz gar goo arg2 arg1 arg0
f
fgaz gar goo arg2 arg1 arg0


Related Topics



Leave a reply



Submit