简体   繁体   English

我如何在bash中传递完整的参数列表,同时将多字参数保持在一起?

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

I am having some issues with word-splitting in bash variable expansion. 我在bash变量扩展中遇到单词拆分问题。 I want to be able to store an argument list in a variable and run it, but any quoted multiword arguments aren't evaluating how I expected them to. 我希望能够将参数列表存储在变量中并运行它,但是任何带引号的多字参数都无法评估我的期望。

I'll explain my problem with an example. 我将用一个例子来解释我的问题。 Lets say I had a function decho that printed each positional parameter on it's own line: 可以说我有一个函数decho ,它在自己的行上打印了每个位置参数:

#!/bin/bash -u
while [ $# -gt 0 ]; do
  echo $1
  shift
done

Ok, if I go decho ab "cd" I get: 好吧,如果我去decho ab "cd"我得到:

[~]$ decho a b "c d"
a
b
c d

Which is what I expect and want. 这是我期望和想要的。 But on the other hand if I get the arguments list from a variable I get this: 但是另一方面,如果我从变量获取参数列表,则会得到以下信息:

[~]$ args='a b "c d"'
[~]$ decho $args
a
b
"c
d"

Which is not what I want. 这不是我想要的。 I can go: 我可以去:

[~]$ echo decho $args | bash
a
b
c d

But that seems a little clunky. 但这似乎有些笨拙。 Is there a better way to make the expansion of $args in decho $args be word-split the way I expected? 有没有更好的方法可以使decho $args$args扩展按我期望的方式拆分?

您可以使用:

eval decho $args

You can move the eval inside the script: 您可以在脚本内移动评估:

#!/bin/bash -u
eval set -- $*
for i; 
do 
  echo $i;
done

Now you can do: 现在您可以执行以下操作:

$ args='a b "c d"'
$ decho $args
a
b
c d

but you'll have to quote the arguments if you pass them on the CL: 但是如果在CL上传递参数,则必须引用这些参数:

$ decho 'a b "c d"'
a
b
c d

It is fundamentally flawed to attempt to pass an argument list stored in a variable, to a command. 从根本上说,试图将存储在变量中的参数列表传递给命令是有缺陷的。

Presumably, if you have code somewhere to create a variable containing the intended args. 大概,如果您在某处有代码来创建一个包含预期参数的变量。 for a command, then you can change it to instead store the args into an array variable: 对于命令,则可以将其更改为将args存储到数组变量中:

decho_argv=(a b 'c d')  # <-- easy!

Then, rather than changing the command "decho" to accommodate the args taken from a plain variable (which will break its ability to handle normal args) you can do: 然后,可以执行以下操作,而不是更改命令“ decho”以容纳从普通变量中获取的args(这将破坏其处理常规args的能力):

decho "${decho_argv[@]}"  # USE DOUBLE QUOTES!!!

However, if you are the situation where you are trying to take arbitrary input which is expected to be string fields corresponding to intended command positional arguments, and you want to pass those arguments to a command, then you should instead of using a variable, read the data into an array. 但是,如果您正在尝试采用任意输入(预期是与预期的命令位置参数相对应的字符串字段)的情况,并且想要将这些参数传递给命令,则应该使用变量而不是变量,数据放入数组。

Note that suggestions which offer the use of eval to set positional parameters with the contents of an ordinary variable are extremely dangerous. 请注意,建议使用eval来设置具有普通变量内容的位置参数非常危险。

Because, exposing the contents of a variable to the quote-removal and word-splitting on the command-line affords no way to protect against shell metachars in the string in the variable from causing havoc. 因为,在命令行上将变量的内容暴露于引号删除和单词拆分的过程中,无法防止变量字符串中的shell metachar引起破坏。

Eg, imagine in the following example if the word "man" was replaced with the two words "rm" and "-rf" and the final arg word was "*": 例如,假设在下面的示例中,是否将单词“ man”替换为两个单词“ rm”和“ -rf”,而最后一个arg单词为“ *”:

Do Not Do This: 不要这样做:

> args='arg1 ; man arg4'
> eval set -- $args
No manual entry for arg4
> eval set -- "$args"        # This is no better
No manual entry for arg4
> eval "set -- $args"        # Still hopeless
No manual entry for arg4

> eval "set -- '$args'"  # making it safe also makes it not work at all!
> echo "$1"
arg1 ; man arg4

Have you tried: 你有没有尝试过:

for arg in "$@"
do
        echo "arg $i:$arg:"
        let "i+=1"
done

Should yield something like: 应该产生如下内容:

arg 1: a
arg 2: c d

in your case. 在你的情况下。

Straight from memory, no guarantee :-) 直接从内存中,不能保证:-)

hmmm.. eval decho $args works too: eval decho $args .. eval decho $args也可以:

[~]$ eval decho $args
a
b
c d

And I may be able to do something with bash arrays using "${array[@]}" (which works like "$@" ), but then I would have to write code to load the array, which would be a pain. 而且我也许可以使用"${array[@]}" (类似于"$@" )对bash数组进行某些操作,但是随后我将不得不编写代码来加载数组,这很痛苦。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM