fed*_*qui 173 unix bash shell escaping special-characters
是否有任何需要在Bash中转义的完整字符列表?可以用它来检查sed
吗?
特别是,我正在检查是否%
需要转义.我试过了
echo "h%h" | sed 's/%/i/g'
Run Code Online (Sandbox Code Playgroud)
工作得很好,没有逃脱%
.这是否意味着%
不需要逃脱?这是检查必要性的好方法吗?
而更普遍的:它们是相同的字符,以逃避shell
和bash
?
Jo *_* So 235
有两个简单而安全的规则,不仅适用于工作,sh
也适用于bash
.
这适用于除单引号本身之外的所有字符.要逃避单引号,请关闭之前的引号,插入单引号,然后重新打开引号.
'I'\''m a s@fe $tring which ends in newline
'
Run Code Online (Sandbox Code Playgroud)
sed命令: sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
这适用于除换行符之外的所有字符.对于换行符,请使用单引号或双引号.仍然必须处理空字符串 - 替换为""
\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"
"
Run Code Online (Sandbox Code Playgroud)
sed命令:sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.
有一个简单安全的字符集,例如[a-zA-Z0-9,._+:@%/-]
,可以保留未转义的字符以使其更具可读性
I\'m\ a\ s@fe\ \$tring\ which\ ends\ in\ newline"
"
Run Code Online (Sandbox Code Playgroud)
sed命令: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链接的参考手册)
F. *_*uri 47
为这种请求构建了一个特殊的 printf
格式指令(%q
):
printf [-v var] format [arguments]
Run Code Online (Sandbox Code Playgroud)%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'
Run Code Online (Sandbox Code Playgroud)
这也可以通过变量使用:
printf -v var "%q" "$foo
"
echo "$var"
$'Hello world\n'
Run Code Online (Sandbox Code Playgroud)
请注意,必须转义从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
Run Code Online (Sandbox Code Playgroud)
这必须呈现如下:
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
Run Code Online (Sandbox Code Playgroud)
第一个字段是byte的hexa值,第二E
个字段包含if字符需要转义而第三个字段显示转义字符的转义.
,
?你可以看到一些角色,不总是需要进行转义,如,
,}
和{
.
所以不经常,但有时:
echo test 1, 2, 3 and 4,5.
test 1, 2, 3 and 4,5.
Run Code Online (Sandbox Code Playgroud)
要么
echo test { 1, 2, 3 }
test { 1, 2, 3 }
Run Code Online (Sandbox Code Playgroud)
但要小心:
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
Run Code Online (Sandbox Code Playgroud)
Mat*_*hew 32
为了节省别人不必RTFM ...在bash中:
在双引号包围的字符保留了引号中的所有字符的字面意义,例外
$
,`
,\
,和,启用了历史扩展的时候,!
.
...所以,如果你逃避那些(当然还有报价本身),你可能还可以.
如果你采取更保守的"有疑问,逃避它"的方法,应该可以通过不转义标识符字符(即ASCII字母,数字或'_')来避免获得具有特殊含义的字符.它们不太可能(即在一些奇怪的POSIX-ish shell中)具有特殊含义,因此需要进行转义.
cod*_*ter 23
使用这种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
Run Code Online (Sandbox Code Playgroud)
它给出了这个输出:
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
Run Code Online (Sandbox Code Playgroud)
一些结果,,
看起来有点可疑.获得@ CharlesDuffy的投入会很有趣.
cda*_*rke 18
需要转义的字符在Bourne或POSIX shell中与Bash不同.通常(非常)Bash是这些shell的超集,所以你逃脱的任何东西都shell
应该在Bash中转义.
一个很好的一般规则是"如果有疑问,就逃避它".但逃避一些角色给了他们一个特殊的意义,比如\n
.这些列在man bash
下面的页面Quoting
和echo
.
除此之外,逃避任何不是字母数字的字符,它更安全.我不知道一个明确的清单.
手册页将它们列在某处,但不在一个地方.学习语言,这是确定的方法.
一个让我感到困惑的是!
.这是Bash(和csh)中的特殊字符(历史扩展),但不是Korn shell中的特殊字符.甚至echo "Hello world!"
出问题.像往常一样使用单引号删除了特殊含义.
小智 5
我注意到 bash 在使用自动完成功能时会自动转义一些字符。
例如,如果您有一个名为 的目录dir:A
,bash 将自动完成dir\:A
使用它,我使用 ASCII 表的字符运行了一些实验并得出以下列表:
bash 在自动完成时转义的字符:(包括空格)
!"$&'()*,:;<=>?@[\]^`{|}
Run Code Online (Sandbox Code Playgroud)
bash 不会转义的字符:
#%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~
Run Code Online (Sandbox Code Playgroud)
(我排除了/
,因为它不能用于目录名称)