How to Pass Command Line Parameters with Quotes Stored in Single Variable

How to pass command line parameters with quotes stored in single variable?

Answering my own question. BIG thanks goes to pzanoni.
xargs seems to parse correctly anything you are throwing to it :-)
"$@", "$", $@ and $ works good with it. So my code now looks like:

#!/bin/sh

pass() {
echo $* | xargs ./sh_param
}

pass '"single param" separate params'

And result is what I wanted:

Param: single param
Param: separate
Param: params

Expansion of variables inside single quotes in a command in Bash

Inside single quotes everything is preserved literally, without exception.

That means you have to close the quotes, insert something, and then re-enter again.

'before'"$variable"'after'
'before'"'"'after'
'before'\''after'

Word concatenation is simply done by juxtaposition. As you can verify, each of the above lines is a single word to the shell. Quotes (single or double quotes, depending on the situation) don't isolate words. They are only used to disable interpretation of various special characters, like whitespace, $, ;... For a good tutorial on quoting see Mark Reed's answer. Also relevant: Which characters need to be escaped in bash?

Do not concatenate strings interpreted by a shell

You should absolutely avoid building shell commands by concatenating variables. This is a bad idea similar to concatenation of SQL fragments (SQL injection!).

Usually it is possible to have placeholders in the command, and to supply the command together with variables so that the callee can receive them from the invocation arguments list.

For example, the following is very unsafe. DON'T DO THIS

script="echo \"Argument 1 is: $myvar\""
/bin/sh -c "$script"

If the contents of $myvar is untrusted, here is an exploit:

myvar='foo"; echo "you were hacked'

Instead of the above invocation, use positional arguments. The following invocation is better -- it's not exploitable:

script='echo "arg 1 is: $1"'
/bin/sh -c "$script" -- "$myvar"

Note the use of single ticks in the assignment to script, which means that it's taken literally, without variable expansion or any other form of interpretation.

How do I pass on script arguments that contain quotes/spaces?

Use "$@" with quotes:

prog="$1"
"$@"
ecode="$?"
echo "$prog exited with $ecode"

This will pass each argument exactly as it was received. If you don't include the quotes, each element will be split according to $IFS:

  • "$@" is like "$1" "$2" "$3" ..., passing each element as a separate argument.
  • "$*" is like "$1 $2 $3 ...", passing all elements concatenated as a single argument
  • $* and $@ is like $1 $2 $3 ..., breaking up each element on whitespace, expanding all globs, and passing each resulting word as a separate element ($IFS).

The same is true for arrays, such as "${array[@]}" and "${array[*]}"

How would I make a variable of type args take a quote or string as an argument among others?

You can treat quoted text as one string without using the Split function, instead making use of Regex.
Take the following snippet as an example:

// In your case just read from the textBox for input
string input = "cars \"testing string\"";

// This code will split the input string along spaces,
// while keeping quoted strings together
string[] tmp = Regex.Split(input,
"(?<=^[^\"]*(?:\"[^\"]*\"[^\"]*)*) (?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");

// Now must remove the quotes from the Regex'd string
string[] args = tmp.Select(str => str.Replace("\"", "")).ToArray();

// Now when printing the arguments, they are correctly split
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine("args[" + i + "]:'" + args[i] + "'");
}

I found the particular regex string you needed at this link, here on stack overflow.

Keep quotes in $args using PowerShell

The only way I can think of without being able to modify the input parameters would still require modifying the command called somewhat.

In order to preserve the quotes, perhaps try capturing the full command-line that the PowerShell script was called with.

So I put this in the test1.ps1 script:

Write-Host (Get-WmiObject -Query "select CommandLine from Win32_Process where CommandLine like '%test1%'").CommandLine

Then this is what is returned if the script is called in this manner:

PS C:\temp> powershell .\test1.ps1 a=application o="this object" msg_text="this is a text"
"C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe" .\test1.ps1 a=application "o=this object" "msg_text=this is a text"

This is only possible if a new instance of PowerShell is called, however, otherwise the parameters won't be available by this method:

PS C:\temp> .\test1.ps1 a=application o="this object" msg_text="this is a text" > zzz3.txt

PS C:\temp>

Of course if this approach is taken, you'll then need to parse the input arguments manually, which you might be able to do with help of the $args object. It's a long-shot, but does preserve the quotes.

How to quotes in bash function parameters?

The reason this happens is because bash interprets the arguments, as you thought. The quotes simply aren't there any more when it calls the function, so this isn't possible. It worked in DOS because programs could interpret the command line themselves, not that it helps you!



Related Topics



Leave a reply



Submit