basic concept01: String
本文所有的测试例如无特殊说明,均based on fish shell
就从字符串说起吧,啥是字符串就不用解释了,我们来看几个简单的例子
?> ~ set param abc ?> ~ echo "string with blank and $param surrounded with double quotation marks" string with blank and abc surrounded with double quotation marks ?> ~ echo ‘string with blank and $param surrounded with single quotation marks‘ string with blank and $param surrounded with single quotation marks
注意到$parm展开后的区别了吗?这里涉及到我要讲的第一个concept
Concept 01 shell字符串替换:
单引号字符串,shell不做字符串替换
双引号字符串,shell做字符串替换
这是单引号字符串与双引号字符串的区别,那么不加单引号或者双引号的字符串与这两者有什么区别呢?
看下面的例子
?> ~ echo "$param" abc ?> ~ echo $param abc
这两条命令都对字符串进行了替换(变量展开),这两条命令效果完全相同。那么没有单引号/双引号的字符串究竟有什么区别呢?
让我们进入bash中写一个例子
[email protected]:~$ x=123 [email protected]-virtual-machine:~$ y=123 456 No command ‘456‘ found, did you mean: Command ‘a56‘ from package ‘a56‘ (universe) 456: command not found [email protected]-virtual-machine:~$ z="123 456" [email protected]-virtual-machine:~$ echo $x 123 [email protected]-virtual-machine:~$ echo $y [email protected]-virtual-machine:~$ echo $z 123 456 [email protected]-virtual-machine:~$
看到y变量的赋值报语法错误了吗?无单/双引号的字符串,以空格/回车作为字符串的起始和结束,除此以外,等同于双引号字符串
ok,让我们暂时总结一下, version 01 of concept 01:
1. shell会对字符串做替换
2. shell通过单引号,双引号识别字符串的border,当没有单/双引号时,以空格/回车作为border
3. 单引号字符串不做字符串替换,其他两种都做字符串替换
shell会替换哪些字符串呢?让我们继续来看几个例子
?> ~ set param abc ?> ~ echo "$param" abc ?> ~ echo "\$param" $param ?> ~ echo (ls) Desktop Documents Downloads examples.desktop linux_shell.txt Music Pictures Public PycharmProjects pycharm register keys record software Templates Videos workspace ?> ~ [email protected]-virtual-machine:~$ echo `ls` Desktop Documents Downloads examples.desktop linux_shell.txt Music Pictures Public PycharmProjects pycharm register keys record software Templates Videos workspace [email protected]-virtual-machine:~$
请注意最后一个例子在bash中执行,`ls`使用反引号,即按键1(不是小键盘的按键1)旁边的键(不按shift)
看明白啦吗?反引号字符串,fish中用圆括号替代,是替换成程序的输出结果。让我们继续总结一下, version 02 of concept 01:
1. shell会对字符串做替换:变量替换($param)、转义字符替换(\$)、程序标准输出替换(`ls`)
2. shell通过单引号,双引号识别字符串的border,当没有单/双引号时,以空格/回车作为border
3. 单引号字符串不做字符串替换,其他两种都做字符串替换
Concept01基本就介绍完了。没错,这个系列写的是本人多年以来对技术的理解和总结,自然不会只有这么一点肤浅的内容。
那么接下来,让我们再看几个例子:
sample 01:
?> ~ set x (echo hello) ?> ~ echo $x hello ?> ~ set y (aaa) No command ‘aaa‘ found, did you mean: Command ‘jaaa‘ from package ‘jaaa‘ (universe) Command ‘aa‘ from package ‘astronomical-almanac‘ (universe) Command ‘aha‘ from package ‘aha‘ (universe) Command ‘ara‘ from package ‘ara‘ (universe) aaa: command not found ?> ~ echo $y ?> ~
看到了吗,shell只会使用程序的标准输出(stdout)来替换用()或者反引号的字符串,而stderr虽然也是输出信息,但是并不会被用来替换
version 03 of concept01:
1. shell会对字符串做替换:变量替换、转义字符替换、程序标准输出替换(only stdout, exclude stderr)
2. shell通过单引号,双引号识别字符串的border,当没有单/双引号时,以空格/回车作为border
3. 单引号字符串不做字符串替换,其他两种都做字符串替换
sample 02:
?> ~ echo "abc 123" abc 123 ?> ~ echo "abc \"123\"" abc "123" ?> ~ echo "abc ‘123‘" abc ‘123‘ ?> ~ echo ‘abc 123‘ abc 123 ?> ~ echo ‘abc \‘123\‘‘ abc ‘123‘ ?> ~ echo ‘abc "123"‘ abc "123" ?> ~
1. single quotation marks字符串中的escaping character \‘会被替换
2. double quotation marks字符串中的escaping character \"会被替换
3. single quotation marks and double quotation marks可以嵌套使用
让我们再总结一下:
version 04 of Concept01
1. shell会对字符串做替换:变量替换、转义字符替换、程序标准输出替换(only stdout, exclude stderr)
2. shell通过单引号,双引号识别字符串的border,当没有单/双引号时,以空格/回车作为border
3. 单引号字符串不做字符串替换,其他两种都做字符串替换。但是单引号字符串中的单引号需要使用转义字符,会被替换。双引号字符串中的双引号需要使用转义字符
sample 03:
?> ~ set param abc ?> ~ set p ‘$param‘ ?> ~ echo "$p" $param ?> ~
$p的值$param并没有被递归替换
version 05 of Concept01:
1. shell会对字符串做替换:变量替换、转义字符替换、程序标准输出替换(only stdout, exclude stderr). 不会递归替换
2. shell通过单引号,双引号识别字符串的border,当没有单/双引号时,以空格/回车作为border
3. 单引号字符串不做字符串替换,其他两种都做字符串替换。但是单引号字符串中的单引号需要使用转义字符,会被替换。双引号字符串中的双引号需要使用转义字符
sample 04:
?> ~ echo 1 (echo 2 (echo 3 abc)) 1 2 3 abc
version 06 of Concept01:
1. shell会对字符串做替换:变量替换、转义字符替换、程序标准输出替换(only stdout, exclude stderr). 不会递归替换
2. shell通过单引号,双引号识别字符串的border,当没有单/双引号时,以空格/回车作为border
3. 单引号字符串不做字符串替换,其他两种都做字符串替换。但是单引号字符串中的单引号需要使用转义字符,会被替换。双引号字符串中的双引号需要使用转义字符
4. 圆括号/反引号可以嵌套使用
关于shell中的字符串概念的分析就到此为止了,其实并不复杂,你觉得的?
shell script中的字符串难点在于除了shell本身会对字符串做替换,命令,尤其是使用正则表达式的grep egrep sed也会对字符串做替换,当这些过程mixed,才会真正让人迷惑。
这是下一篇要讲的了。
第二篇的引子:
问题1:
既然不加单双引号的字符串以空格/回车作为border,那么为什么下面这两组命令效果是相同的:
?> ~ echo abc 123
abc 123
?> ~ set param this is a string with blank, but without single/double qutation marks
?> ~ echo $param
this is a string with blank, but without single/double qutation marks
?> ~
?> ~ echo "abc 123"
abc 123
?> ~ set param "this is a string with blank, but without single/double qutation marks"
?> ~ echo $param
this is a string with blank, but without single/double qutation marks
?> ~
问题2:
试看下面几条命令的执行情况
?> ~ echo abc.def abcxdef | grep ‘abc.def‘ --color=auto
abc.def abcxdef
?> ~ echo abc.def abcxdef | grep ‘abc\.def‘ --color=auto
abc.def abcxdef
?> ~
?> ~ echo abc.def abcxdef | grep ‘*.def‘ --color=auto
?> ~ echo abc.def abcxdef | grep -E ‘*.def‘ --color=auto
abc.def abcxdef
?> ~