# 注释
1. 表示注释 #注释
2. 在引号中间和\#等表示#本身
3.echo ${PATH#*:} # 参数替换,不是一个注释
4.echo $(( 2#101011 )) # 数制转换,不是一个注释
echo "The # here does not begin a comment."
echo 'The # here does not begin a comment.'
echo The \# here does not begin a comment.
echo The # 这里开始一个注释.
echo ${PATH#*:} # 参数替换, 不是一个注释.
echo $(( 2#101011 )) # 数制转换, 不是一个注释.
这里特别要注意第四个,一定要有空格,否则不认同是注释
; 分隔
1.命令分隔,在一行中写多个命令 echo "aa" ; echo "bb"
2.在条件中的if和then如果放在同一行,也用;分隔
;; case条件的结束
1.命令分隔,在一行中写多个命令 echo "aa" ; echo "bb"
2.在条件中的if和then如果放在同一行,也用;分隔
echo hello; echo there
if [ -x "$filename" ]; then # 注意: "if"和"then"需要分隔.
echo "File $filename exists."; cp $filename $filename.bak
else
echo "File $filename not found."; touch $filename
fi; echo "File test complete."
. 命令相当于
1.命令:source
2.文件名的前缀,隐藏文件
3.目录:.当前目录,..父目录
4.正则表达式:匹配任意单个字符
首先,先举例说明一下"."作为source使用的实例
#!/bin/bash
. data-file # 加载一个数据文件.
# 与"source data-file"效果相同, 但是更具可移植性.
# 文件"data-file"必须存在于当前工作目录, 因为这个文件是使用'basename'来引用的.
echo "variable1 = $variable1"
echo "variable3 = $variable3"
let "sum = $variable2 + $variable4"
echo "sum = $sum"
exit 0
上面是编写的include_file脚本,通过 . data-file引入,相当于c语言中的include data-file,我们看看data-file的内容
# 这是需要被脚本加载的数据文件.
# 这种文件可以包含变量, 函数, 等等.
# 在脚本中可以通过'source'或者'.'命令来加载.
# 让我们初始化一些变量.
variable1=22
variable2=474
variable3=5
variable4=97
message1="Hello, how are you?"
message2="Enough for now. Goodbye."
接下来我们看看脚本的执行结果:
root@ubuntu:~/resource/study/shell_study# chmod 777 include_file
root@ubuntu:~/resource/study/shell_study# ls
clear_log data-file include_file show_self
root@ubuntu:~/resource/study/shell_study# ./include_file
variable1 = 22
variable3 = 5
sum = 571
上面的结果已经很有力的说明了我们想要的结论
.作为隐藏文件时,建立隐藏文件的方法:touch .data-file
.作为匹配字符说明如下:ab. 可以表示ab+任意字符,处理换行,并且必须是一个字符ab.不能表示ab
"" 部分引用 支持通配符扩展
"STRING"将会阻止(解释)STRING中大部分特殊的字符
' ‘ 全引用,不进行通配符扩展
'STRING'将会阻止STRING中所有特殊字符的解释. 这是一种比使用"更强烈的形式
\ 转义
\X将会"转义"字符X. 这等价于"X", 也等价于'X'. \通常用来转义"和', 这样双引号和单引号就不会被解释成特殊含义了.
/ 目录分隔符
分隔文件名不同的部分(比如 /home/bozo/projects/Makefile).也可以用来作为除法算术操作符.
, 多个命令都被执行,但返回最后一个
逗号操作符链接了一系列的算术操作. 虽然里边所有的内容都被运行了,但只有最后一项被返回.
let "t2 = ((a = 9, 15 / 3))" # Set "a = 9" and "t2 = 15 / 3"
逗号之前会运算,但是只有最后一项被返回
` 后置引用
`command`结构可以将命令的输出赋值到一个变量中去.
cd $LOG_DIR
if [ `pwd` != "$LOG_DIR" ]
then
echo "Can't change to $LOG_DIR"
exit $E_XCD
fi
这里例子是最有力的的说明,在上一章中只不过没有到这个方法,这里pwd命令会返回当前路径,然后与LOG_DIR进行比较,同样你可以定义一个变量保存pwd返回的内容,比如:
path=`pwd`
: 操作符
1.空操作,等价于"NOP" (no op, 一个什么也不干的命令).
1 :
2 echo $? # 0
2.死循环: while :,可以被认为与shell的内建命令,与true作用相同.
while :
do
operation-1
operation-2
...
operation-n
done
# 与下边相同:
# while true
# do
# ...
# done
3.在if/then中表示什么都不做,引出分支
if condition
then : # 什么都不做,引出分支.
else
take-some-action
fi
4.设置默认参数 : ${username=`whoami`}
: ${username=`whoami`}
# ${username=`whoami`} 如果没有开头的":"的话, 将会给出一个错误, 除非"username"是一个命令或者内建命令
5.变量替换 : ${HOSTNAME?} ${USER?} ${MAIL?}
: ${HOSTNAME?} ${USER?} ${MAIL?}
# 如果一个或多个必要的环境变量没被设置的话, 就打印错误信息.
6.在和 > (重定向操作符)结合使用时,把一个文件截断到0 长度,没有修改它的权限;如果文件在之前并不存在,那么就创建它.如:
: > data.xxx #文件"data.xxx"现在被清空了. 与 cat /dev/null >data.xxx 的作用相同 然而,这不会产生一个新的进程,因为":"是一个内建命令.
在和>>重定向操作符结合使用时,将不会对想要附加的文件产生任何影响.
如果文件不存在,将创建.
7.可能用来作为注释行, 虽然我们不推荐这么做. 使用#来注释的话, 将关闭剩余行的错误检查, 所以可以在注释行中写任何东西. 然而, 使用:的话将不会这样.
: This is a comment that generates an error, ( if [ $x -eq 3] ).
8.":"还用来在/etc/passwd和$PATH变量中做分隔符.
bash$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games
* 匹配0个或多个字符;数学乘法;**幂运算
root@ubuntu:~/resource/study/shell_study# ls
clear_log data-file include_file show_self
root@ubuntu:~/resource/study/shell_study# echo *
clear_log data-file include_file show_self
? 匹配任意一个字符;但在((a>b?a:b))表示c语言中的三目运算
(( t = a<45?7:11 )) # C语言风格的三元操作.
$ 字符
1.取变量的值 echo $PATH
var1=5
var2=23skidoo
echo $var1 # 5
echo $var2 # 23skidoo
2.正则表达式中表示行的结尾
在正则表达式中, "$"表示行结束符,先分析一下下面的例子吧
root@ubuntu:~/resource/study/shell_study# echo slfjalj$fdjgl
slfjalj
3.${} 参数替换 ${PAHT}
#!/bin/bash
2 # param-sub.sh
3
4 # 一个变量是否被声明或设置,
5 #+ 将会影响这个变量是否使用默认值,
6 #+ 即使这个变量值为空(null).
7
8 username0=
9 echo "username0 has been declared, but is set to null."
10 echo "username0 = ${username0-`whoami`}"这里定义了username0且初始化是null,所以这里不会有输出,这里的“-”相当于“=”
11 # 不会有输出.
12
13 echo
14
15 echo username1 has not been declared.
16 echo "username1 = ${username1-`whoami`}"这里username1在上面没有定义并初始化为null,所以会显示
17 # 将会输出默认值.
18
19 username2=
20 echo "username2 has been declared, but is set to null."
21 echo "username2 = ${username2:-`whoami`}"这里上面初始化了username2并初始化为null,但是这里有个“:”
22 # ^
23 # 会输出, 因为:-会比-多一个条件测试.
24 # 可以与上边的例子比较一下.
25
26
27 #
28
29 # 再来一个:
30
31 variable=
32 # 变量已经被声明, 但是设为空值.
33
34 echo "${variable-0}" # (没有输出)
35 echo "${variable:-1}" # 1
36 # ^
37
38 unset variable
39
40 echo "${variable-2}" # 2
41 echo "${variable:-3}" # 3
42
43 exit 0
我们也看看他的执行结果:
root@ubuntu:~/resource/study/shell_study# chmod 777 para_sub
root@ubuntu:~/resource/study/shell_study# ls
clear_log data-file include_file para_sub show_self
root@ubuntu:~/resource/study/shell_study# ./para_sub
username0 has been declared, but is set to null.
username0 =
username1 has not been declared.
username1 = root
username2 has been declared, but is set to null.
username2 = root ^
1
2
3
4.$* 所有参数
5.$# 参数个数
6.$$ 进程的ID
7.$? 进程的返回状态
( )字符
1.命令组,在一个子Shell中运行 (a=3;echo $a) 其中定义的变量在后面不可用
在括号中的变量,由于是在子shell中,所以对于脚本剩下的部分是不可用的. 父进程, 也就是脚本本身, 将不能够读取在子进程中创建的变量, 也就是在子shell中创建的变量.
1 a=123
2 ( a=321; )
3
4 echo "a = $a" # a = 123
5 # 在圆括号中a变量, 更像是一个局部变量.
2.数组初始化: array=(a,b,c)
大括号扩展
1 cat {file1,file2,file3} > combined_file