如何将带双引号的空字符串传递给 bash 脚本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23305076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:18:37  来源:igfitidea点击:

How do I pass an empty string with double quotes to a bash script?

bashshell

提问by Josh

I'm trying to write a script that will accept as additional arguments on the command line an empty string with double quotes. I want the script to pass those arguments along with the double quoted empty string if that is provided, but instead the command interpreter seems to interpret such an argument as an empty string and strips away the quotes. Is there any way to do this?

我正在尝试编写一个脚本,该脚本将在命令行上接受带双引号的空字符串作为附加参数。我希望脚本将这些参数与双引号空字符串一起传递(如果提供),但命令解释器似乎将此类参数解释为空字符串并去掉引号。有没有办法做到这一点?

As a simple example I would have in the file script.sh:

作为一个简单的例子,我在文件 script.sh 中有:

#!/bin/bash
/home/myapp  

If I run at the prompt:

如果我在提示符下运行:

$ ./script.sh arg1 ""

The script just executes "/home/myapp arg1", but misses/ignores the second argument (""). I want it to preserve this empty string and instead execute: /home/myapp arg1 ""

脚本只是执行"/home/myapp arg1",但错过/忽略第二个参数("")。我希望它保留这个空字符串并执行:/home/myapp arg1 ""

采纳答案by Digital Trauma

You can detect how many positional parameters were passed to your script by examining the $#parameter. For example, if this is 2 or greater, then you know that something was passed for $2, even if $2is empty (quotes removed by calling shell). The following implements that logic, and passes ""to the called program (in this case echo) if the parameter was passed but empty:

您可以通过检查$#参数来检测传递给脚本的位置参数的数量。例如,如果这是 2 或更大,那么您就知道为 传递了一些东西$2,即使$2是空的(通过调用 shell 删除了引号)。下面实现了该逻辑,如果参数被传递但为空,则传递""给被调用的程序(在本例中echo):

#!/bin/bash

if [ $# -ge 2 ]; then
    if [ "" ]; then
        arg2=""
    else
        arg2='""'
    fi
    echo " $arg2"
elif [ $# == 1 ]; then
    echo ""
fi

Output:

输出:

$ ./args.sh a
a
$ ./args.sh a ""
a ""
$ ./args.sh a 1
a 1
$ 

回答by Kaz

You are correctly passing an empty string argument to the script.

您正确地将空字符串参数传递给脚本。

It is the script that is messing it up:

是脚本搞砸了:

#!/bin/bash
/home/myapp  

The script is not protecting the expansion of $1and $2from word-splitting. This means that if $1and $2contain multiple words, those turn into individual arguments, and if either of them expand to nothing, they simply disappear.

该脚本不保护分词的扩展$1$2分词。这意味着如果$1$2包含多个单词,它们会变成单独的参数,如果它们中的任何一个扩展为空,它们就会消失。

This should be:

这应该是:

#!/bin/bash
/home/myapp "" ""

In general, you can make your script pass all of its arguments to the invoked program, like this:

通常,您可以让脚本将其所有参数传递给被调用的程序,如下所示:

/home/myapp "$@"

The quotes are just shell syntax; they are not part of the argument data itself. When you type program ""into the shell, at the operating system level, the program receives an empty C language string: a pointer to a null byte. There are no quotes.

引号只是 shell 语法;它们不是参数数据本身的一部分。当您program ""在 shell 中键入时,在操作系统级别,程序会收到一个空的 C 语言字符串:一个指向空字节的指针。没有引号。

You can pass the argument ""(a two-character string made of two double quotes) but that is not an empty argument. A way to do that is, for instance, '""': wrap it in single quotes.

您可以传递参数""(由两个双引号组成的两字符字符串),但这不是空参数。例如,一种方法是'""':将它用单引号括起来。

The only reason to do things like that is when you're manipulating shell syntax at a meta-level: passing around pieces of shell script source code, such as quoted tokens, empty or otherwise. The shell has a command called evalwhich takes source code as an argument (or multiple arguments) and evaluates it.

这样做的唯一原因是当您在元级别操作 shell 语法时:传递 shell 脚本源代码片段,例如带引号的标记、空的或其他的。shell 有一个名为的命令eval,它将源代码作为一个参数(或多个参数)并对其进行评估。

empty_shell_string_syntax='""'    # this variable holds the characters ""

eval empty_var=$empty_shell_string_syntax   # empty_var gets set to empty string

before evalis invoked, the command line is subject to expansion. That expansion removes the syntax $empty_shell_string_sytnaxand replaces it with the contents, the characters "". So then eval gets the string empty_var="". It evaluates this, and so empty_varis set to the empty string, as the syntax indicates.

eval调用之前,命令行会被扩展。该扩展删除了语法$empty_shell_string_sytnax并将其替换为内容,即字符""。然后 eval 得到字符串empty_var=""。它对此进行评估,因此empty_var被设置为空字符串,如语法所示。

回答by mklement0

To complement Kaz's helpful explanation:
If you pass "$@"through, emptyarguments will be passed through, too:

补充Kaz 的有用解释
如果您通过,"$@"通过参数

#!/bin/bash

/home/myapp "$@"

Passing through "$@"preserves the original arguments exactlyas passed in - even arguments passed as empty strings(passed as, e.g., ''or ""or "$someVar", where variable someVaris unset or contains an empty string).

传递完全按照传入的方式"$@"保留原始参数- 甚至作为空字符串传递的参数(作为传递,例如,or或,其中变量未设置或包含空字符串)。''"""$someVar"someVar



In case there can be more than 2 arguments:

如果可以有2 个以上的参数

#!/bin/bash

# Copy the (up to) first 2 arguments - whether they're empty strings or not -
# to a separate array.
firstTwo=("${@:1:2}") 
shift; shift  # Remove the first 2 arguments from the arguments array.

# Invoke the app with the (up to) first 2 arguments stored in the new array.
/home/myapp "${firstTwo[@]}"

# Process the remaining arguments, if any.
for a; do
  echo "remaining: [$a]"
done

回答by Jan Vlcinsky

You shall escape it using backslash

你应该使用反斜杠转义它

$ ./script.sh arg1 \"\"

Can be tested e.g. on echo:

可以在例如回声上进行测试:

$ echo \"\"
""

回答by ooga

Escape them with backslashes or put them in single quotes.

用反斜杠将它们转义或将它们放在单引号中。

回答by iamauser

You can also put them inside a single quote to have their literal values, e.g. :

您还可以将它们放在单引号内以获取它们的文字值,例如:

  ]$ echo '""'
  ""

For example, in a script:

例如,在脚本中:

   ]# cat a.bash
     #!/bin/bash        
     echo ab

  ]$ ./a.sh '""'
  a""b

  ]$ ./a.sh ""
  ab

回答by alphasoup

Try this:

尝试这个:

cmd=yourcomand;
n=0; for a in "$@"; do n=$((n +1)); cmd="$cmd ${$n+\"$$n\"}"; done
eval $cmd