首页 > 代码库 > linux shell script: Basic concept01 - String

linux shell script: Basic concept01 - String

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中写一个例子

redstar@redstar-virtual-machine:~$ x=123
redstar@redstar-virtual-machine:~$ y=123 456
No command 456 found, did you mean:
 Command a56 from package a56 (universe)
456: command not found
redstar@redstar-virtual-machine:~$ z="123 456"
redstar@redstar-virtual-machine:~$ echo $x
123
redstar@redstar-virtual-machine:~$ echo $y

redstar@redstar-virtual-machine:~$ echo $z
123 456
redstar@redstar-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
?> ~
redstar@redstar-virtual-machine:~$ echo `ls`
Desktop Documents Downloads examples.desktop linux_shell.txt Music Pictures Public PycharmProjects pycharm register keys record software Templates Videos workspace
redstar@redstar-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
?> ~

linux shell script: Basic concept01 - String