@perkyoung
2018-04-12T06:33:55.000000Z
字数 5790
阅读 1031
运维
'#'井号
#comment 注释
echo "hello"#comment #注意,#和命令不能紧挨着
result=$(( 2#101011 )) #不是注释,是数制转换
特定的模式匹配也可能用到#
';'命令分隔符,可以在一行写多个命令
echo "hello" ; echo "world"
if test $name == 'perkyoung'; then
fi
';;',有时候';'是需要转义的
case name in
perkyoung)
echo "...."
;;
esac
'.',
类似source命令
如果一个文件开头是'.'字符,这个文件是隐藏文件
如果是目录,单独的'.'代表当前目录
正则表达式中,'.'匹配任何单独的字符
','
let "result=((a=10,15/3))" #链接一系列算数操作,虽然都执行了,但是只有最后一个被返回
echo $a #9
echo $result #5
'`'
result=`commands` #命令替换,可以将命令的输出赋值给一个变量。关注后面的后置引用,后置标记
:
: #空命令,什么也不敢,也可以理解为和shell的true作用相同。是bash的内建命令,退出码是0
echo $?
下面是死循环
while :
do
.....
done
下面和上面相同
while true
do
...
done
在if/then中作为占位符
if conditon
then :
fi
清空一个文件
: > ./text.txt #相当于 cat /dev/null > ./text.txt,但是这并不会产生一个新的进程,因为:是内建命令
/etc/passwd, PATH的分隔符
yangpengfei:x:1000:1000:yangpengfei,,,:/home/yangpengfei:/bin/bash
'!'
if grep perkyoung /etc/passwd #取反命令的退出码
if $a != 10
'*'
ls * #文件的通配符
\d* #正则表达式中,这个表示任何个数字,包括0个
* #乘法
** #幂运算
'$'
echo $result #引用变量
$? #返回码
${} #参数替换
$*, $@ #位置参数, $* 所有的参数作为一个字符串,$@是每个参数作为一个独立的单词,for i in $@ ;do ....done,使用的时候都被引用起来,只有这样,她俩才会不同
shift #去掉$1,$@指向剩余的参数
$! #运行在后台的最后一个作业的pid,
$_ #保存着之前命令的最后一个参数值
$$ #当前进程的pid,一般用来构造唯一临时文件名。
'()'命令组
(a=10; echo $a) 命令组,将括号内的命令列表,作为一个子shell来运行,所以内部的变量更像是一个内部变量,外部的父shell是无法获取里面的变量的
Array=(1 3 4 5) #初始化数组
'{xxx,yyy,zzz}'大括号扩展
cat {file1,file2,file3} > file #将三个文件联合起来写到file中,注意,这三个文件中间不能有空格
cp file.{txt,backup} #拷贝file.txt,file.backup
'{}'
内部组,其实是创建了一个匿名函数,但是里面的变量对外部还是可见的。与()不同的是,大括号不会开启一个新的shell
a=123
{ a=321 }
echo "a=$a" # a=321
#代码块与文件重定向
#!/bin/bash
FILE=./tmp
{
read line1
read line2
} < $FILE
echo line1
echo line2
#将一个代码块结果重定向到文件
#!/bin/bash
{
echo ""
commands
} > file.txt
'&' 后台运行一个命令
ls -l & #有时候在后台运行一个命令,整个脚本就挂起了,解决方案是在接下来一行添加wait
wait
'(())'
整数扩展
扩展并计算括号内的表达式
'> &> >& >> < <>'
command >filename #重定向到filename
command &>filename #重定向stdout,stderr到filename
command >&2 #重定向stdout到stderr
[i]<>filename #打开filename,读写,如果没有则创建,分配文件描述符i
'[]'
正则,索引
if [[ $a > $b ]]
then
commands
fi
'\<,\>'
grep '\<perkyoung\>' ./test #单词的边界
'-'
用于重定向stdin或stdout
(cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)
等同于 cp -a /source/directory/* /dest/directory
引用变量的值,叫做变量替换 $
result=23 #变量不带$,一般是变量被声明,被赋值,unset,或者export
echo $result #这个这是引用的简写形式,如果遇到什么问题,就需要用${result}了
echo "$result" #如果是双引号,则变量的替换是不能被阻止的,又成为部分引用或弱引用
echo '$result' #如果是单引号,则变量的替换完全被阻止,成为全引用或者部分引用
举例,赋值和替换
a=332
hello=$a
variable=value #一定不能有空格,如果是variable =value,将被解释为,variable是一个命令,后面是参数。如果是variable= value将被解释为,执行了一个value命令,并且添加了一个环境变量,该变量的值为空。
hello="a b c d" #有空格的时候一定要加引号
echo $hello #a b c d
echo "$hello" #a b c d , 输出结果不同,所以如果是引用变量,则保留空白,如果是变量替换,则不保留空白
let a=16+5 #一般最好加上双引号吧,因为如果是 a +=1,这种,不加引号是不行的
for循环赋值
read赋值
a=`ls -l` 命令赋值,注意在引用a的时候要加上"$a",这样里面的tab都会引用到
a=$(ls -l) 这个和上面的几乎一样。只是一种更新的方法
bash是不区分类型的,所有的都是字符串,当然也进行比较操作和整数操作,关键因素是里面是不是全是数字
result=1234
tmp=${result/23/bb} #将23替换为bb
环境变量
如果一个脚本要设置一个环境变量, 那么需要将这些变量"export"出来, 也就是需要通知到脚本
本地的环境. 这是export命令的功能.
位置参数
$1,$2,$3......${10},${11} #超过9之后,就需要用大括号了
args=$# #参数个数
lastargs=${!args} #如果想取得最后一个参数,如果$4代表最后一个,那如何引用这个4呢,就用到了间接引用或者用${!#},注意不是${!$#}
shift #除$0外,将所有参数左移,
$
表示不取'\101\102\103\104' 八进制数编码
任何一个函数,或者进程都会返回一个状态吗,例如exit 0,状态吗0-255,如果没有这个exit指令,则退出码是最后一次执行的指令的退出码
if/then来判断命令列表的退出码是否为0,在unix中0代表成功,如果成功的话,则执行接下来的指令
[]
if [ $a -eq $b ] if test $a -eq $b
终于明白了,这个是内建命令,和test功能一致,测试内部的比较表达式,根据比较的结果返回一个退出码,0表示真,1表示假
[[]] 扩展测试命令,比[]更通用,&&,||,<,>可以非常正常得出现在其中,不会出现逻辑错误,test也无法胜任这种情况。
if [[ $a == $b ]]
((...)) let
let "1<2" return 0
(( 0 && 1 )) #查看算数表达式的结果,如果为非0,则返回退出码0,表示正确
(( 0 )) #这个值为0,所以返回错误,也就是返回值为非0的值
if能测试任何命令,不仅仅是中括号中的条件
if grep -q "perkyoung" /etc/passwd 这个太赞了。
if echo "hello" | grep -q "./file"
a="./aa"
b="./bb"
if cmp $a $b &> /dev/null
then
反过来,[]也不一定非要用if,[ $a -eq $b ] && commands #这样也行
-e 文件存在
-s 文件大小不为0
-h 这是一个符号链接
-L 同上
-S socket
-t 被关联到一个终端设备上
-g sgid是否被标记在文件上
-u suid是否被标记在文件上
-O 是否是文件的拥有者
-N 从文件上一次被读到现在是否被修改过
f1 -nt f2 f1比f2更新
f1 -ot f2 f1比f2更旧
f1 -et f2 是相同的硬链接
(( n=n+1 ))
n=$((n+1))
let "n++"
let "a+=1"
((n++))
<< 左移一位
let "value<<=2" 左移两位,并赋值
& 按位与
&=
| 按位或
~ 按位反
! 按位非
^ 按位异或XOR
^=
let "t=032" #八进制
let "t=0x11" #16进制
let "t=2#11" #用11表示一个2进制的书,base#number
内容不少,以后可以当做手册来看
字符串长度
${#string}
len=`expr length $string`
匹配字符串开头的子串长度
expr match "$string" '$substring' #$substring是一个正则表达式
或 expr "$string" : '$substring'
string="abcdABCD123abcABC"
len=`expr match "$string" 'abcd[A-Z]*'` #8从头开始匹配了8个字符
索引
expr index $string $substring
在string中匹配到的第一次出现substring的位置
string="abcdABCD123abcABC"
echo `expr index "$string" '[A-Z]*'` #结果为5
提取子串
${string:position} #从position位置开始提取子串,从0开始计数
${string:position:length} #
string="abcdABCD123abcABC"
echo ${string:3:3} #dAB
echo ${string: -4} ; echo ${string:(-4)}; echo ${string:(-4):3} #从右边截取,截取后四个,注意要有空格或者括号
echo ${*:2} #如果不提供变量,则截取的就是命令行的参数,这个是从第二个开始到最后面的参数
echo ${@:2}
echo ${*:2:3}
expr substr $string $position $length
expr match "$string" '\($substring\)' #从开头位置匹配substring,substring是一个正则表达式
或者expr "$string" : '\($substring\)' #同上
子串消除
${string#substring} #从开头位置节点最短匹配的$substring,这里也是开头位置
${string##substring} #从开头位置节点最长匹配的$substring,这里也是开头位置
string="abcdABCD123abcABC"
echo ${string#a*c} #dABCD123abcABC
echo ${string##a*c} #ABC
${string%substring} #从结尾,截取最短
${string%%substring}#同上,截取最长
子串替换
${string/$substring/$replacement} #使用replacement来替换第一个匹配的substring
${string//$substring/$replacement} #使用replacement来替换所有匹配的substring
${string/#$substring/$replacement} #如果substring匹配开头的字符,使用replacement来替换开头的串
${string/$$substring/$replacement} #如果substring匹配结尾的字符,使用replacement来替换结尾的串
${parameter} #可以和字符串组合起来实用
${param=default} #如果变量没有被声明,则值为default
${param:=default} #如果变量没有被设置,则值为default
echo "username=${username=`whoami`}
username=
echo "username=${username:=`whoami`}
${param+alt_value} #如果变量已经被声明,那么值就是后者,否则为null
${param:+alt_value} #如果变量已经被设置,则值为后者,否则为null
${param?err_msg} #如果变量被声明,就使用设置的值,否则打印err_msg
${parma:?err_msg} #如果变量被设置,就使用设置的值,否则打印err_msg
: ${HOSTNAME?} ${USER?}
declare -r 创建只读变量
-i 创建int类型
-a 数组
-f 函数
-x export变量
-x val=$value export变量
并且declare可以限制变量的作用域,比如函数内部declare了变量VA,那外部是无法引用该变量的。非declare的变量,在外部是可以的使用的
一个变量的值是另一个变量的名字
a=letter_of
letter_of=z
如何通过变量a来获取到z呢?
eval a=\$$a #a=z
或者 a=${!a}
与let很相似,允许算数扩展和赋值,可以认为是bash使用C语言风格的处理机制
#/bin/bash
(( .... ))
(( a = 23 )
(( a++ ))
(( a-- ))
(( ++a ))
(( t = a<45?7:11 ))