bash 如何传递带有特殊字符的参数来调用shell脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42106102/
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 15:44:02  来源:igfitidea点击:

How to pass arguments with special characters to call shell script

linuxbashshellquoting

提问by Ranjit Singh

Calling .sh(shell script) with the required parameters as below :-

使用以下所需参数调用 .sh(shell 脚本):-

sh home/example.sh --context_param dbUserName=username --context_param dbPassword=exam!ple##### --context_param resultDate=2017-01-13

calling example.sh with paramters dbUsername and password but getting following error:-

使用参数 dbUsername 和密码调用 example.sh 但出现以下错误:-

-bash: !ple#####: event not found

-bash: !ple#####: 事件未找到

I think special characters restrict the command to execute. Then how i have to pass the special characters. Any help will be appreciable.

我认为特殊字符会限制要执行的命令。然后我必须如何传递特殊字符。任何帮助将是可观的。

回答by Inian

Change the line,

换线,

dbPassword=exam!ple#####

to,

到,

dbPassword='exam!ple#####'

to avoid !(history-expansion) being treated specially in bash

避免!(历史扩展)被特殊对待bash

From man bashunder QUOTINGsub-section,

man bashQUOTING分节,

When the command history expansion facilities are being used (see HISTORY EXPANSION below), the history expansion character, usually !, must be quoted to prevent history expansion.

当使用命令历史扩展工具时(请参阅下面的 HISTORY EXPANSION),必须引用历史扩展字符,通常是 !,以防止历史扩展。

more under HISTORY EXPANSION

更多下 HISTORY EXPANSION

History expansions are introduced by the appearance of the history expansion character, which is ! by default. Only backslash (\) and single quotes can quote the history expansion character.

历史扩展是由历史扩展字符的出现引入的,即 ! 默认情况下。只有反斜杠 ( \) 和单引号可以引用历史扩展字符。

Also, it is a good practice to quote all your name-valuepairs to prevent Word-splitting done by shell.

此外,引用所有name-value对以防止 shell 进行分词也是一种很好的做法。

sh home/example.sh --context_param dbUserName="username" --context_param dbPassword='exam!ple#####' --context_param resultDate="2017-01-13"

About word-splitting, from the manpage,

关于分词,从man页面,

Word Splitting

The shell scans the results of parameter expansion, command substitution, and arithmetic expansion that did not occur within double quotes for word splitting. The shell treats each character of IFSas a delimiter, and splits the results of the other expansions into words using these characters as field terminators

分词

shell 扫描没有出现在双引号内的参数扩展、命令替换和算术扩展的结果以进行分词。shell 将 的每个字符IFS视为分隔符,并使用这些字符作为字段终止符将其他扩展的结果拆分为单词

回答by aslavkin

Pass it like this:

像这样传递它:

exam\!ple\#\#\#\#\#

Test:

测试:

echo exam\!ple\#\#\#\#\#

回答by Prashant Pokhriyal

You can do the following two things:

你可以做以下两件事:

  1. Escape every single special symbol with a backslash

    sh home/example.sh --context_param dbUserName=username --context_param dbPassword=exam\!ple\#\#\#\#\# --context_param resultDate=2017-01-13
    
  2. Singlequote the entire argument.

    sh home/example.sh --context_param dbUserName=username --context_param dbPassword='exam!ple#####' --context_param resultDate=2017-01-13
    
  1. 用反斜杠转义每个特殊符号

    sh home/example.sh --context_param dbUserName=username --context_param dbPassword=exam\!ple\#\#\#\#\# --context_param resultDate=2017-01-13
    
  2. 单引号整个参数

    sh home/example.sh --context_param dbUserName=username --context_param dbPassword='exam!ple#####' --context_param resultDate=2017-01-13
    

From man bash

man bash

QUOTING

Quoting is used to remove the special meaning of certain characters or words to the shell. Quoting can be used to disable special treatment for special characters, to prevent reserved words from being recognized as such, and to prevent parameter expansion.

When the command history expansion facilities are being used, the history expansion character,usually !,must be quoted to prevent history expansion.

There are three quoting mechanisms: the escape character, single quotes, and double quotes.

A non-quoted backslash (\)is the escape character. It preserves the literal value of the next character that follows, with the exception of <newline>. If a \<newline>pair appears, and the backslash is not itself quoted, the \<newline>is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).

Enclosing characters in single quotespreserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.

Enclosing characters in double quotespreserves the literal value of all characters within the quotes, with the exception of $,`,\, and, when history expansion is enabled, !. The characters $and ` retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or <newline>. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an !appearing in double quotes is escaped using a backslash. The backslash preceding the !is not removed.

The special parameters *and @have special meaning when in double quotes.

Words of the form $'string'are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.

Backslash escape sequences, if present, are decoded as follows:

          \a     alert (bell)
          \b     backspace
          \e
          \E     an escape character
          \f     form feed
          \n     new line
          \r     carriage return
          \t     horizontal tab
          \v     vertical tab
          \     backslash
          \'     single quote
          \"     double quote
          \nnn   the eight-bit character whose value is the octal value nnn (one to three digits)
          \xHH   the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
          \uHHHH the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits)
          \UHHHHHHHH
                 the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits)
          \cx    a control-x character

The expanded result is single-quoted, as if the dollar sign had not been present.

A double-quoted string preceded by a dollar sign ($"string") will cause the string to be translated according to the current locale. If the current locale is C or POSIX, the dollar sign is ignored. If the string is translated and replaced, the replacement is double-quoted.

引用

引用用于删除某些字符或单词对 shell 的特殊含义。引用可用于禁用对特殊字符的特殊处理,防止保留字被识别为此类,并防止参数扩展。

当使用命令历史扩展工具时,通常!必须引用历史扩展字符以防止历史扩展。

共有三种引用机制:转义符单引号双引号

一个非引用的反斜杠(\)是转义字符。它保留了下一个字符的字面值,除了<newline>. 如果一\<newline>对出现,并且反斜杠本身没有被引用,则将\<newline>其视为行继续(即,它从输入流中删除并有效地被忽略)。

将字符括在单引号中会保留引号内每个字符的字面值。单引号之间不能出现单引号,即使前面有反斜杠。

用双引号将字符括起来会保留引号内所有字符的字面值,但$,`, \, 和当启用历史扩展时,!. 字符$和 ` 在双引号内保留其特殊含义。反斜杠保留其特殊含义,随后仅在由以下字符之一:$`, ,"\<newline>。双引号可以通过在双引号前面加上反斜杠来引用。如果启用,将执行历史扩展,除非!使用反斜杠转义双引号中的出现。前面的反斜杠!不会被删除。

双引号中的特殊参数*@具有特殊含义。

表格$'string'中的词被特殊处理。单词扩展为字符串,并按照 ANSI C 标准的规定替换反斜杠转义字符。

反斜杠转义序列(如果存在)按如下方式解码:

          \a     alert (bell)
          \b     backspace
          \e
          \E     an escape character
          \f     form feed
          \n     new line
          \r     carriage return
          \t     horizontal tab
          \v     vertical tab
          \     backslash
          \'     single quote
          \"     double quote
          \nnn   the eight-bit character whose value is the octal value nnn (one to three digits)
          \xHH   the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
          \uHHHH the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits)
          \UHHHHHHHH
                 the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits)
          \cx    a control-x character

扩展结果是单引号的,就好像美元符号不存在一样。

以美元符号 ($"string") 开头的双引号字符串将使字符串根据当前语言环境进行翻译。如果当前语言环境是 C 或 POSIX,则忽略美元符号。如果字符串被翻译和替换,则替换是双引号。