Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Bash时需要转义哪些字符?_Bash_Shell_Unix_Escaping_Special Characters - Fatal编程技术网

使用Bash时需要转义哪些字符?

使用Bash时需要转义哪些字符?,bash,shell,unix,escaping,special-characters,Bash,Shell,Unix,Escaping,Special Characters,在Bash中是否有需要转义的字符的完整列表?是否可以仅使用sed进行检查 特别是,我正在检查%是否需要转义。我试过了 echo "h%h" | sed 's/%/i/g' 工作正常,没有逃逸%。这是否意味着%不需要转义?这是检查必要性的好方法吗 更一般的是:它们在shell和bash中转义的字符是否相同?需要转义的字符在Bourne或POSIX shell中与bash不同。通常(非常)Bash是这些shell的超集,因此在shell中转义的任何内容都应该在Bash中转义 一个很好的一般规则是“

在Bash中是否有需要转义的字符的完整列表?是否可以仅使用
sed
进行检查

特别是,我正在检查
%
是否需要转义。我试过了

echo "h%h" | sed 's/%/i/g'
工作正常,没有逃逸
%
。这是否意味着
%
不需要转义?这是检查必要性的好方法吗


更一般的是:它们在
shell
bash
中转义的字符是否相同?

需要转义的字符在Bourne或POSIX shell中与bash不同。通常(非常)Bash是这些shell的超集,因此在
shell
中转义的任何内容都应该在Bash中转义

一个很好的一般规则是“如果有疑问,就逃避它”。但是对某些字符进行转义会赋予它们特殊的含义,如
\n
。它们列在
manbash
页面的
Quoting
echo

除此之外,转义任何非字母数字的字符更安全。我不知道有哪一个确切的清单

手册页列出了它们的全部位置,但不在一个地方。学习语言,这是确定的方法


让我抓狂的是
。这是Bash(和csh)中的一个特殊字符(历史扩展),但在kornshell中不是。即使是
echo“Hello world!”
也会出现问题。像往常一样,使用单引号会删除特殊含义。

我猜您是在谈论bash字符串。不同类型的字符串对转义有不同的要求。单引号字符串不同于双引号字符串

最好的参考是bash手册的一节


它解释了哪些字符需要转义。请注意,某些字符可能需要转义,这取决于启用了哪些选项,例如历史扩展。

有两个简单而安全的规则,不仅适用于
sh
,也适用于
bash

1.将整个字符串放在单引号中 这适用于除单引号本身之外的所有字符。若要转义单引号,请关闭其前面的引号,插入单引号,然后重新打开引号

'I'\''m a s@fe $tring which ends in newline
'
sed命令:
sed-e“s/'/'\\\'/g;1s/^/'/;\$s/\$/'/'”

2.用反斜杠转义每个字符 这适用于除换行符以外的所有字符。对于换行符,请使用单引号或双引号。仍然必须处理空字符串-替换为
“”

sed命令:
sed-e的s//\\&/g;1{$s/^$/“”/};1.s/^/“/;$!s/$/”/“/”

2b。更具可读性的版本2 有一组简单安全的字符,如
[a-zA-Z0-9,.+:@%/-]
,可以将其保留为不替换,以使其更具可读性

I\'m\ a\ s@fe\ \$tring\ which\ ends\ in\ newline"
"
sed命令:
LC\u ALL=C sed-e's/[^a-zA-Z0-9,.\uu+@%/-]/\\\&/g;1{$s/^$/“”/};1.s/^/“/;$!s/$/”/“/”


请注意,在sed程序中,无法知道输入的最后一行是否以换行字节结尾(空时除外)。这就是为什么上面两个sed命令都假定它不是。可以手动添加带引号的换行符

注意,shell变量仅为POSIX意义上的文本定义。未定义处理二进制数据。对于重要的实现,二进制可以工作,NUL字节除外(因为变量是用C字符串实现的,并且意味着用作C字符串,即程序参数),但是您应该切换到“二进制”语言环境,如拉丁语1



(您可以通过阅读POSIX规范来轻松验证规则。
sh
。对于bash,请检查@AustinPhillips链接的规则)

以避免其他人不得不使用RTFM。。。在bash中:

将字符括在双引号中会保留引号中所有字符的文字值,但
$
`
\
以及启用历史扩展时的
除外

…因此,如果你逃避这些(当然还有引用本身),你可能就没事了

如果您采取更保守的“当有疑问时,转义它”方法,则可以通过不转义标识符字符(即ASCII字母、数字或“"”)来避免获取具有特殊含义的字符。它们不太可能(例如,在某些奇怪的POSIX ish shell中)有特殊的含义,因此需要转义。

可以重用为shell输入的格式
for i in {0..127} ;do
    printf -v var \\%o $i
    printf -v var $var
    printf -v res "%q" "$var"
    esc=E
    [ "$var" = "$res" ] && esc=-
    printf "%02X %s %-7s\n" $i $esc "$res"
done |
    column
2021年2月编辑:
${var@Q}
在bash下,您可以使用参数扩展的
@
命令存储变量内容以进行参数转换:

样本:

$ var=$'Hello\nGood world.\n'
$ echo "$var"
Hello
Good world.

$ echo "${var@Q}"
$'Hello\nGood world.\n'

$ echo "${var@A}"
var=$'Hello\nGood world.\n'
旧答案 有一个特殊的
printf
格式指令(
%q
)是为这种请求生成的:

printf[-v var]格式[参数]

 %q     causes printf to output the corresponding argument
        in a format that can be reused as shell input.
一些样本: 这也可以通过变量使用:

printf -v var "%q" "$foo
"
echo "$var"
$'Hello world\n'
使用所有(128)ascii字节进行快速检查: 请注意,从128到255的所有字节都必须转义

for i in {0..127} ;do
    printf -v var \\%o $i
    printf -v var $var
    printf -v res "%q" "$var"
    esc=E
    [ "$var" = "$res" ] && esc=-
    printf "%02X %s %-7s\n" $i $esc "$res"
done |
    column
这必须呈现如下内容:

00 E ''         1A E $'\032'    34 - 4          4E - N          68 - h      
01 E $'\001'    1B E $'\E'      35 - 5          4F - O          69 - i      
02 E $'\002'    1C E $'\034'    36 - 6          50 - P          6A - j      
03 E $'\003'    1D E $'\035'    37 - 7          51 - Q          6B - k      
04 E $'\004'    1E E $'\036'    38 - 8          52 - R          6C - l      
05 E $'\005'    1F E $'\037'    39 - 9          53 - S          6D - m      
06 E $'\006'    20 E \          3A - :          54 - T          6E - n      
07 E $'\a'      21 E \!         3B E \;         55 - U          6F - o      
08 E $'\b'      22 E \"         3C E \<         56 - V          70 - p      
09 E $'\t'      23 E \#         3D - =          57 - W          71 - q      
0A E $'\n'      24 E \$         3E E \>         58 - X          72 - r      
0B E $'\v'      25 - %          3F E \?         59 - Y          73 - s      
0C E $'\f'      26 E \&         40 - @          5A - Z          74 - t      
0D E $'\r'      27 E \'         41 - A          5B E \[         75 - u      
0E E $'\016'    28 E \(         42 - B          5C E \\         76 - v      
0F E $'\017'    29 E \)         43 - C          5D E \]         77 - w      
10 E $'\020'    2A E \*         44 - D          5E E \^         78 - x      
11 E $'\021'    2B - +          45 - E          5F - _          79 - y      
12 E $'\022'    2C E \,         46 - F          60 E \`         7A - z      
13 E $'\023'    2D - -          47 - G          61 - a          7B E \{     
14 E $'\024'    2E - .          48 - H          62 - b          7C E \|     
15 E $'\025'    2F - /          49 - I          63 - c          7D E \}     
16 E $'\026'    30 - 0          4A - J          64 - d          7E E \~     
17 E $'\027'    31 - 1          4B - K          65 - e          7F E $'\177'
18 E $'\030'    32 - 2          4C - L          66 - f      
19 E $'\031'    33 - 3          4D - M          67 - g      

但请注意:

echo test{1,2,3}
test1 test2 test3

echo test\ {1,2,3}
test 1 test 2 test 3

echo test\ {\ 1,\ 2,\ 3\ }
test  1 test  2 test  3

echo test\ {\ 1\,\ 2,\ 3\ }
test  1, 2 test  3 

我注意到bash在使用autocomplete时会自动转义一些字符

例如,如果您有一个名为
dir:a
的目录,bash将自动完成到
dir\:a

利用这一点,我使用ASCII表的字符进行了一些实验,并得出以下列表:

bash在自动完成时转义的字符:(包括空格)


(我排除了
/
,因为它不能在目录名中使用)

使用
打印“%q”
,我们可以运行一个循环来找出哪些字符是特殊的:

#!/bin/bash
special=$'`!@#$%^&*()-_+={}|[]\\;\':",.<>?/ '
for ((i=0; i < ${#special}; i++)); do
    char="${special:i:1}"
    printf -v q_char '%q' "$char"
    if [[ "$char" != "$q_char" ]]; then
        printf 'Yes - character %s needs to be escaped\n' "$char"
    else
        printf 'No - character %s does not need to be escaped\n' "$char"
    fi
done | sort
#/bin/bash
特殊=$'`!@$%^&*()-_+={}|[]\\;\':",.?/ '
for((i=0;i<${special};i++)do
char=“${special:i:1}”
printf-v q_字符“%q'$char”
如果[[“$char”!=“$q_char”];那么
printf“是-需要转义字符%s”\n“$char”
其他的
printf'否-字符%s不需要转义\n'$char'
fi
完成|排序
echo test 1, 2, 3 and 4,5.
test 1, 2, 3 and 4,5.
echo test { 1, 2, 3 }
test { 1, 2, 3 }
echo test{1,2,3}
test1 test2 test3

echo test\ {1,2,3}
test 1 test 2 test 3

echo test\ {\ 1,\ 2,\ 3\ }
test  1 test  2 test  3

echo test\ {\ 1\,\ 2,\ 3\ }
test  1, 2 test  3 
 !"$&'()*,:;<=>?@[\]^`{|}
#%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~
#!/bin/bash
special=$'`!@#$%^&*()-_+={}|[]\\;\':",.<>?/ '
for ((i=0; i < ${#special}; i++)); do
    char="${special:i:1}"
    printf -v q_char '%q' "$char"
    if [[ "$char" != "$q_char" ]]; then
        printf 'Yes - character %s needs to be escaped\n' "$char"
    else
        printf 'No - character %s does not need to be escaped\n' "$char"
    fi
done | sort
No, character % does not need to be escaped
No, character + does not need to be escaped
No, character - does not need to be escaped
No, character . does not need to be escaped
No, character / does not need to be escaped
No, character : does not need to be escaped
No, character = does not need to be escaped
No, character @ does not need to be escaped
No, character _ does not need to be escaped
Yes, character   needs to be escaped
Yes, character ! needs to be escaped
Yes, character " needs to be escaped
Yes, character # needs to be escaped
Yes, character $ needs to be escaped
Yes, character & needs to be escaped
Yes, character ' needs to be escaped
Yes, character ( needs to be escaped
Yes, character ) needs to be escaped
Yes, character * needs to be escaped
Yes, character , needs to be escaped
Yes, character ; needs to be escaped
Yes, character < needs to be escaped
Yes, character > needs to be escaped
Yes, character ? needs to be escaped
Yes, character [ needs to be escaped
Yes, character \ needs to be escaped
Yes, character ] needs to be escaped
Yes, character ^ needs to be escaped
Yes, character ` needs to be escaped
Yes, character { needs to be escaped
Yes, character | needs to be escaped
Yes, character } needs to be escaped