哪些字符需要使用bash时要逃脱?(Which characters need to be esca

2019-08-19 05:10发布

是否有需要在Bash中转义字符的任何完整列表? 可它只是检查sed

尤其是,我被检查是否%需要进行转义或没有。 我试过了

echo "h%h" | sed 's/%/i/g'

和工作正常,没有逃逸% 。 这是否意味着%并不需要进行转义? 这是检查的必要性的好办法?

而更普遍的:它们是相同的字符,在逃跑shellbash

Answer 1:

有两个工作,这不仅容易和安全规则, shbash

1.将用单引号将整个字符串

这适用于除单引号本身所有的字符。 为了逃避单引号,关闭报价之前,插入单引号,并重新打开引用。

'I'\''m a s@fe $tring which ends in newline
'

但该命令: sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"

2.使用反斜线每字符

这适用于除换行符的所有字符。 对于换行符使用单或双引号。 空字符串仍然必须处理-替换为""

\I\'\m\ \a\ \s\@\f\e\ \$\t\r\i\n\g\ \w\h\i\c\h\ \e\n\d\s\ \i\n\ \n\e\w\l\i\n\e"
"

sed命令: sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' 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_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/' LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'


请注意,在SED方案,一个不知道输入的最后一行是否与换行符字节结束(除非它是空的)。 这就是为什么这两个以上的sed命令假定它没有。 您可以手动添加引用换行符。

需要注意的是shell变量只在POSIX意义的文本定义。 处理二进制数据没有限定。 对于这个问题的实现,二进制作品与NUL字节除外(因变量与C字符串实施,意味着作为C字符串,即程序参数),但你应该切换到“二进制”的语言环境,如LATIN1 。


(你可以很容易地通过阅读对POSIX规范验证规则sh 。对于bash,检查由@AustinPhillips链接的参考手册)



Answer 2:

可重复使用作为外壳的输入格式

有一个特殊 printf格式指令( %q对于这种要求建):

的printf [-v变种]格式[参数]

  %q causes printf to output the corresponding argument in a format that can be reused as shell input. 

一些样本:

read foo
Hello world
printf "%q\n" "$foo"
Hello\ world

printf "%q\n" $'Hello world!\n'
$'Hello world!\n'

这可以通过变量被使用过:

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      

其中第一场是一个字节的十六进制值,第二包含E如果角色需要进行转义和第三场演出转义字符的演示文稿。

为什么,

你可以看到一些字符并不总是需要进行转义,比如,}{

所以并不总是而是时间一段

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 


Answer 3:

为了节省别人不必RTFM ...在bash:

在双引号包围的字符保留了引号中的所有字符的字面意义,例外$`\ ,并且,当历史扩充被启用, !

......所以如果你逃避那些(与报价本身,当然)你可能没问题。

如果采取了较为保守的“有疑问时,逃吧”的做法,应该是可以避免,而不是越来越有特殊含义的字符由不转义字符识别(即ASCII字母,数字或“_”)。 这不太可能,这些将永远(即在一些奇怪的POSIX十岁上下壳)具有特殊的意义,因此需要进行转义。



Answer 4:

需要转义字符在Bourne或POSIX外壳比猛砸不同。 一般来说(非常)Bash是那些炮弹的超集,所以任何你在逃避shell应猛砸进行转义。

一个很好的一般规则是“如果有疑问,逃吧”。 但逃避一些字符让他们有一个特殊的意义,像\n 。 这些列在man bash下页Quotingecho

除此之外,逃避不是字母的任何字符,是比较安全的。 我不知道一个明确的名单。

该手册页列出所有这些地方,但不是在一个地方。 学习语言,这是可以肯定的方式。

一个已经引起了我出去的! 。 这是一个特殊字符(历史扩展)中的Bash(和csh),但不是在Korn shell中。 即使echo "Hello world!" 给人的问题。 使用单引号,像往常一样,消除了特殊的意义。



Answer 5:

使用print '%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

它给出了这样的输出:

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

一些结果,比如,看起来有点可疑。 很想得到@ CharlesDuffy对这一投入。



Answer 6:

我假定你在谈论bash的字符串。 有不同的类型,其具有一组不同的转义要求的字符串。 例如。 单引号字符串是由双引号的字符串不同。

最好的参考是引用 bash的手动部分。

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



Answer 7:

我注意到使用自动完成时自动bash的转义一些字符。

举例来说,如果你有一个名为dir:A ,bash将自动完成对dir\:A

利用这一点,我拼命地跑使用ASCII表中的字符一些实验,并得出以下列表:

该打坏上自动完成转义字符 (包括空格)

 !"$&'()*,:;<=>?@[\]^`{|}

这打坏不转义字符

#%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~

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



文章来源: Which characters need to be escaped when using Bash?