${parameter@operator}
Parameter transformation. The expansion is either a transforma‐
tion of the value of parameter or information about parameter
itself, depending on the value of operator. Each operator is a
single letter:
Q The expansion is a string that is the value of parameter
quoted in a format that can be reused as input.
...
A The expansion is a string in the form of an assignment
statement or declare command that, if evaluated, will
recreate parameter with its attributes and value.
%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
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
# !/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
7条答案
按热度按时间rjjhvcjd1#
有两个简单而安全的规则,它们不仅在
sh
中有效,而且在bash
中也有效。1.将整个字符串用单引号括起来
这适用于除单引号本身之外的所有字符。要转义单引号,请关闭它前面的引号,插入单引号,然后重新打开引号。
sed命令:
sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
2.用反斜杠转义每个字符
这适用于除换行符以外的所有字符。对于换行符,请使用单引号或双引号。* 仍必须处理空字符串-替换为
""
*sed命令:
sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.2b.可读性更强的版本2
有一个简单安全的字符集,如
[a-zA-Z0-9,._+:@%/-]
,可以不转义以保持其可读性sed命令:
LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.注意,在sed程序中,我们不知道输入的最后一行是否以换行符结束(除非它是空的),这就是为什么上面的两个sed命令都假设它不以换行符结束。
注意,shell变量只定义了POSIX意义上的文本。没有定义处理二进制数据。对于重要的实现,二进制除了NUL字节之外都可以工作(因为变量是用C字符串实现的,并且打算用作C字符串,即程序参数),但是您应该切换到“二进制”语言环境,例如latin 1。
(You通过阅读
sh
的POSIX规范,我可以很容易地验证规则。hlswsv352#
可重复用作shell输入的格式
编辑2021年2月:bash
${var@Q}
在bash下,您可以使用 Parameter Expansion 的
@
命令来存储变量内容,以进行 Parameter transformation:样品:
旧答案
有一个 special
printf
指令(%q
)是为这类请求构建的:printf [-v var]格式[参数]
部分样品:
这也可以通过变量使用:
快速检查所有(128)ascii字节:
请注意,从128到255的所有字节都必须转义。
这必须呈现如下内容:
其中,第一个字段是字节的十六进制值,第二个字段包含
E
(如果字符需要转义),第三个字段显示字符的转义表示。为什么是
,
?您可以看到一些字符并不 * 总是 * 需要转义,如
,
、}
和{
。所以不是 * 总是 * 而是 * 某个时候 *:
或
但是关心:
t2a7ltrp3#
为了让其他人不必在 bash 中进行RTFM......:
将字符括在双引号中会保留引号内所有字符的文字值,但
$
、```、\
和!
(启用历史记录扩展时)除外。......所以如果你避开这些(当然还有引语本身),你可能就没事了。
如果你采取更保守的“当有疑问时,转义它”的方法,通过不转义标识符字符(如ASCII字母、数字或“_”),应该可以避免得到具有特殊含义的字符。这些字符(如在一些奇怪的POSIX类shell中)不太可能有特殊含义,因此需要转义。
taor4pac4#
使用
print '%q'
technique,我们可以运行一个循环来找出哪些字符是特殊字符:它给出以下输出:
有些结果,比如
,
,看起来有点可疑。如果能得到@CharlesDuffy在这方面的意见,会很有趣。lstz6jyr5#
在Bourne或POSIX shell中需要转义的字符与Bash不同。通常(非常)Bash是这些shell的超集,所以在
shell
中转义的任何字符都应该在Bash中转义。一个很好的通用规则是“如果有疑问,就转义它”。但是转义一些字符会给它们带来特殊的含义,比如
\n
。这些字符列在man bash
页面的Quoting
和echo
下。除此之外,转义任何不是字母数字的字符,这样更安全。我不知道一个单一的明确的名单。
手册页在某个地方列出了它们,但不是在一个地方。学习语言,这是确保的方法。
其中一个让我感到困惑的是
!
。这是Bash(和csh)中的一个特殊字符(历史扩展),但在Korn shell中却不是。即使是echo "Hello world!"
也会出现问题。像往常一样,使用单引号会消除这个特殊含义。h4cxqtbf6#
我想你说的是bash字符串。不同类型的字符串对转义有不同的要求。例如,单引号字符串不同于双引号字符串。
最好的参考资料是bash手册的报价部分。
它解释了哪些字符需要转义。请注意,某些字符可能需要转义,这取决于启用了哪些选项,如历史记录扩展。
scyqe7ek7#
我注意到bash在使用自动完成时会自动转义一些字符。
例如,如果您有一个名为
dir:A
的目录,bash将自动完成为dir\:A
使用这个方法,我使用ASCII表的字符运行了一些实验,并得出了以下列表:
(我排除了
/
,因为它不能用于目录名)