井号(#)
注释
以一个#开头的行 (#!是例外) 是注释行 注释也可以出现在一个命令语句的后面 注释行前面也可以有空白字符 在echo命令给出的一个转义的#字符并不会开始一个注释
echo 这里
echo 这里
echo 这里 \ #不是一个注释
echo "这里 #不是一个注释"
echo '这里 #不是一个注释'
分号(;)
命令分割符
分割符允许在同一行里有两个或更多的命令 ”;” 有时需要转义
echo 123 ; echo 456
: "" "
输出:
123
456
"" "
双分号(;;)
case语句分支的结束符
case "${VAR} " in
abc)
echo "\${VAR} = 123"
; ;
xyz)
echo "\${VAR} = 456"
; ;
esac
点(.)
等同于source
. ~/.bash_profile
source ~/.bash_profile
作为一个文件名的组成部分
当点(.)以一个文件名为前缀时,起作用使该文件变成了隐藏文件 作为目录名时,单个点(.)表示当前目录,两个点(…)表示上一级目录
ls -l ~
ls -la ~
cd .
pwd
cd ..
pwd
字符匹配
作为正则表达式的一部分,匹配字符时,单点(.)表示匹配任意一个字符
ls | grep 'l.b'
: "" "
输出:
lib
lib64
"" "
双引号(")
字符串引用(部分引用)
VAR = "Hello $USER "
echo ${VAR}
单引号(')
字符串引用(完全引用)
VAR = 'Hello $USER'
echo ${VAR}
逗号(,)
逗号操作符
用于连接一连串的数学表达式。这一串的数学表达式每一个都被求值,但只有最后一个被返回
let "a=(( b= 1 , 15 / 3 )) "
echo $a
echo $b
后斜杠(\)
转义符
用于单个字符的引用机制 \X "转义"字符为X.它有"引用"X的作用,也等同于直接在单引号里的’X’ \符也可以用于引用双引号(")和单引号('),这时双引号和单引号就表示普通的字符,而不是表示引用了
echo \ x
echo x
echo "x"
echo 'x'
echo \ '
echo \ "
echo "\" "
前斜杠(/)
文件路径的分隔符
mkdir -p /data/pgdata
除法
expr 15 / 3
斜引号(`)
命令替换
引住的命令(command)执行结果能赋值给一个变量
echo ` ls -lh`
冒号(:)
空命令
空操作(即什么操作也不做) 它一般被认为是和shell的内建命令true是一样的 它的退出状态码是真(即0)
:
echo $?
if [ : ] ; then echo '123' ; fi
分隔符
: ${username=`whoami`}
代码块注释,但是会检测注释部分的正确性,否则会报错
: << EOF
echo 1 # 这里是注释,但是一定是能执行的代码,不能执行的命令放这会报错
echo 2 # 这里是注释,但是一定是能执行的代码,不能执行的命令放这会报错
EOF
echo $PATH
: "" "
输出:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/pgsql/bin:/root/bin:/root/bin:/root/bin
"" "
: ${HOSTNAME ?} ${USER ?} ${MAIL?}
变量扩展/子串替换
VAR = 123456789
echo ${VAR: 6}
echo ${VAR: 6: 2}
和重定向符同时使用
和重定向操作符(>)连用, 可以把一个文件的长度截短为零,文件的权限不变 如果文件不存在,则会创建一个新文件
: > tmp
cat /dev/null > tmp
echo '' > tmp
感叹号(!)
取反
if [ "1" != "2" ] ; then echo "true" ; fi
间接引用
a = b
b = 3
eval echo \ $$ a
echo ${! a}
历史命令
在命令行中,感叹号(!)调用属于历史命令机制的调用 在一个脚本里,命令历史机制是被禁止的
! !
星号(*)
通配符
星号(*)字符在用于匹配文件名扩展的一个通配符 它自动匹配给定的目录下的每一个文件
echo *
模式匹配
cd / && ll | grep 'usr*'
算数操作符
星号(*)表示乘法运算符 两个星号(**)表示求幂运算符
let b = "(( a= 2 * 3 , 2 ** 3 )) "
echo $a $b
expr 2 \ * 3
echo $(( 2 * 3 ))
echo $(( 2 ** 3 ))
echo $[ 2 * 3 ]
echo $[ 2 ** 3 ]
问号(?)
测试操作符
在双括号结构里,问号(?)表示 C风格 的三元操作符 在参数替换表达式里,问号(?)测试一个变量是否被设置了值
a = 10 && (( b = a< 30 ? 1 : 2 )) && echo $b
: ${PGDATA?"未设置值"}
通配符
字符?被用于文件名扩展特性的文件名表达式的单字符匹配 在扩展正则表达式中匹配任意一个字符
cd / && ls -lh li?
ls -l | grep -E 'bin?'
美元($)
变量引用
VAR = 1
echo $VAR
行的结尾
echo '123456789' | sed 's/9$/1/'
参数替换
#! /bin/bash
: ${1?"必须给定至少一个选项参数!"}
sh tmp
预定义变量
$0 :代表当前脚本的名称
$! :后台运行的最后一个进程的PID
$? :上一个命令退出的状态(0:成功,非0:失败)
$* :当前shell参数集合(整体)
$$ :表示当前进程ID号码
$# :代表当前shell的参数个数
$@ :当前shell参数集合( 逐个读取)
圆括号(())
命令组
一组由圆括号括起来的命令是新开一个子shell来执行的
a = 1
( a= 2 ; echo $a )
echo $a
数组初始化
array = ( 1 2 3 )
整数扩展
echo $(( 1 + 2 ))
花括号({})
{xxx,yyy,zzz,…}
echo 1 > file1
echo 2 > file2
echo 3 > file3
cat { file1,file2,file3} > combined_file
: "" "
输出:
1
2
3
"" "
cp file4.txt file4.backup
cp file4.{ txt,backup}
在扩展中的所有模式都不能包含空白字符,除非空白字符是被转义或引用的
echo { file1,file2} \ :{ \ A," B" ,' C' }
代码块
这个结构也是一组命令代码块,事实上,它是匿名的函数 与一个函数所不同的,在代码块里的变量仍然能被脚本后面的代码访问
{ local a; a = 1 ; }
a = 1
{ a = 2 ; }
echo $a
由花括号括起的代码块可以引起输入输出的I/O重定向
#! /bin/bash
FILE = /etc/fstab
{
read line1
read line2
} < $FILE
echo "First line in $File is:"
echo "$line1 "
echo
echo "Second line in $File is:"
echo "$line2 "
exit 0
不像一个用圆括号括起来的命令组,一个用花括号括起的代码块不会以一个子shell运行
#! /bin/bash
FILE =~ /test
{
echo 1
echo 2
echo 3
} > $FILE
sh tmp
cat ~/test
: "" "
输出:
1
2
3
"" "
{} \;
路径名,基本上用于find命令里,它不是shell内建的 如果 COMMAND 中包含 {},那么 find 命令将会用所有匹配文件的路径名来替换 “{}”
find ~/ -name 'core*' -exec rm { } \ ;
方括号([ ])
测试
[ 1 -eq 2 ] ; echo $?
[ 1 -eq 1 ] ; echo $?
[ [ 1 -eq 2 ] ] ; echo $?
[ [ 1 -eq 1 ] ] ; echo $?
数组元素
在数组的上下文中,方括号表示数组的每个元素的数字编号
ARRAY = ( 1 2 3 )
echo ${ARRAY[ 0] }
echo ${ARRAY[ 1] }
echo ${ARRAY[ 2] }
字符集的范围
用于正则表达式的一部分,方括号描述一个匹配的字符集范围
echo '12A125ZF' | sed 's/[A-Z]/0/g'
大于小于和(><&)
重定向
ll -lh > ~/tmp.txt
( ll -lh && 错误命令) &> ~/tmp.txt
( ll -lh && 错误命令) > tmp 2 >&1
( ll -lh && 错误命令) > &2 (stderr)
ll -lh >> ~/tmp.txt
cat << EOF
# 这里的注释会被打印
Hello,sqlboy!
EOF
cat <<< Hello,sqlboy!
>| 强迫重定向 (即使noclobber选项设置), 这会强迫覆盖一个存在的文件
echo 111 >| tmp
进程替换
diff < ( ls -lh) < ( ls )
整数比较
expr 1 \ > 2
expr 3 \ > 2
echo $(( 1 > 2 ))
echo $(( 3 > 2 ))
ASCII码比较
[ "a" \ < "A" ] ; echo $?
[ 97 \ < 65 ] ; echo $?
[ [ "a" < "A" ] ] ; echo $?
[ [ 97 < 65 ] ] ; echo $?
[ [ "c" < "t" ] ] ; echo $?
单词界线
cd / && ll -lh | grep '\<lib\>'
后台运行
sleep 10 &
逻辑与
在测试结构中,&&操作只在测试条件两者 都为真时会返回0(成功)
[ [ 1 = 2 && 3 = 3 ] ] ; echo $?
[ 1 = 2 ] && [ 3 = 3 ] ; echo $?
双竖线(||)
逻辑或
在一个测试结构中,||操作符当测试条件的任何一个为真时返回0 (成功)的标志
[ [ 1 = 2 || 3 = 3 ] ] ; echo $?
[ 1 = 2 ] || [ 3 = 3 ] ; echo $?
短线(-)
选项
ls -lh
前缀
[ [ 5 -eq $[ 15 / 3 ] ] ] ; echo $?
重定向
tar cf - .
file -
先前的工作目录
命令cd - 可以回到原来的工作目录,它使用了$OLDPWD 环境变量
cd -; echo $OLDPWD
cd -; echo $OLDPWD
负号或减号
echo $[ 2 -1]
echo $(( 2 - 1 ))
expr 2 - 1
等号(=)
赋值操作符
a = 1 ; echo $a
比较操作符
if [ "1" = "1" ] ; then echo "True" ; fi
加号(+)
加法运算
echo $[ 1 +2]
echo $(( 1 + 2 ))
expr 1 + 2
选项
一些命令和内建命令,用+来启用一些选项,用-来禁用它们
chmod +x tmp.sh
百分号(%)
取模
expr 16 % 3
echo $[ 16 %3]
echo $(( 16 % 3 ))
模式匹配
VAR = 12345678912345
PATTERN = 1 *4
echo ${VAR# $PATTERN}
echo ${VAR## $PATTERN}
PATTERN = 2 *5
echo ${VAR% $PATTERN}
echo ${VAR%% $PATTERN}
波浪号(~)
家目录
echo $HOME
echo ~
当前工作目录
cd /; echo ~+; echo $PWD
: "" "
输出:
/
/
"" "
先前工作目录
cd /; cd /root; echo ~-; echo $OLDPWD
: "" "
输出:
/
/
"" "
正则表达式匹配
[ [ "123456" =~ [ 0 -9] + ] ] ; echo $?
尖号(^)
行首
在正则表达式中, 字符"^"表达匹配一个文本行的开头
ll -lh | grep '^lr'