BASH SHELL
任何一个命令后面须+空格 if_
sed
csb@csb-ThinkPad-E430c:~$ grep csb /etc/passwd
csb:x:1000:1000:CSB,,,:/home/csb:/bin/bash
csb@csb-ThinkPad-E430c:~$ grep csb /etc/passwd|sed 's;csb;cccccccccccc;p'
cccccccccccc:x:1000:1000:CSB,,,:/home/csb:/bin/bash
cccccccccccc:x:1000:1000:CSB,,,:/home/csb:/bin/bash
cut
cut -c list [file..]
cut -f list [-d delim][file...]
-f list 以字段为主,作剪下的操作。list为字段编号或一段范围的列表
-d delim 通过-f选项,使用delim作为定界符
-c list 以字符为主,执行剪下操作
join
join [optinos..] file1 file2
-1 field1 -2 field2 表明结合的字段,-1 field1之从file1中取出field1,而-2 field2指的则为从file2取出field2
-o file.field 输出file文件中的field字段
-t separator
read
read answer 从标准输入读取输入并赋值给变量
read -a arrayname 从单词清单读入一个叫作arrayname的数组里。
read 从输入中读取赋值给内建变量REPLY
read -p 等待输入并将输入赋值给REPLY
declare
declare -i 可以将变量声明为整数
csb@csb-ThinkPad-E430c:~$ declare -i num
csb@csb-ThinkPad-E430c:~$ num=xxx
csb@csb-ThinkPad-E430c:~$ echo $num
0
csb@csb-ThinkPad-E430c:~$ num=4-2
csb@csb-ThinkPad-E430c:~$ echo $num
2
csb@csb-ThinkPad-E430c:~$ num=2^2
csb@csb-ThinkPad-E430c:~$ echo $num
0
csb@csb-ThinkPad-E430c:~$ num=2*2
csb@csb-ThinkPad-E430c:~$ echo $num
4
n=进制#数字 ;表达‘数字‘为几进制
csb@csb-ThinkPad-E430c:~$ num=16#16
csb@csb-ThinkPad-E430c:~$ echo $num
22
csb@csb-ThinkPad-E430c:~$ num=f
csb@csb-ThinkPad-E430c:~$ echo $num
0
csb@csb-ThinkPad-E430c:~$ num=0xf
csb@csb-ThinkPad-E430c:~$ echo $num
15
位置参量
$0 引用脚本名称
$# 获得位置参量的个数
$* 列位置参量清单
$@ 同上
”$*" 扩展为一个参数
“$@” 扩展为彼此分隔的参数 eg 'ba cd' cs cd ='ba cd' 'cs' 'cd'
$1....$[10] 引用单个位置参量
set 用于重置位置参量
if ${变量:?0} ;then //判断变量是否存在不存再不执行if。
for i in $@($*)
do
...
done
test命令操作符
[ s1=s2 ] s1=s2?
[ s1==s2 ]
[ s1!=s2 ] s1!=s2
[string] string不空
[ -z string ] string length=0
[ -n string ] string length!=0
[ -l string ] string length
[ string1 -a string2 ] string1 and string2 is truth
[ string1 -o string2 ] string1 or string2 is truth
[!string1] not match string
[[ x&&y ]] x and y are truth
[[ x||y ]] x or y are trhth
[[ !pattern ]] not match pattern //因为含有元字符,需要使用复合test[[ ]]
[ int1 -eq int2 ] int1=int2
[ int1 -ne int2 ] int1!=int2
[ int1 -gt int2 ] int1>int2
[ int1 -ge int2] int1>=int2
[ int1 -lt int2 ] int
[ int1 -le int2 ] int1<=int2
文件判断中的二进制操作
[ file1 -nt file2 ] file1 newer than file2
[ file1 -ot file2 ] file1 older than file2
[ file1 -ef file2 ] file1与file2 有相同的设备或者I结点数
let命令操作符(())
-
+(一元减和加) ! ~(逻辑否) + - * / % >>逻辑左移 <<逻辑右移
if 命令
#!
echo "are you ok?y/n"
read answer
if [[ $answer==y || $answer==y ]]; //含有|| && 元字符复合test
then
echo "glad to hear that"
fi
#!
echo "are you ok?y/n"
read answer
if [ "$answer"==y -o "$answer"==y ]; //字符串判断包含在引号中 “$answer”
then
echo "glad to hear that"
fi
if [ ! "${BUILD_DIR}" ] ; then //此处[]是test的变形,‘[’,']'后面需要有空格
BUILD_DIR="."
fi
csb@csb-ThinkPad-E430c:~$ declare -i a=5,s=20
csb@csb-ThinkPad-E430c:~$ [ $a -gt $s ] //-gt大于
csb@csb-ThinkPad-E430c:~$ echo $?
1 //?=1,说明条件 $a -gt $s 为假
csb@csb-ThinkPad-E430c:~$ [ $a -le $s ] //-le 小于
csb@csb-ThinkPad-E430c:~$ echo $?
0
csb@csb-ThinkPad-E430c:~$ [[ $name==[[Tt]* ]] //[[ $XXX ]] 表示复合test
csb@csb-ThinkPad-E430c:~$ echo $?
0
exit
exit 用来结束脚本返回命令行,给exit命令的参数保存在?变量中。
exit 0 //正常退出命令
#!
if [ $# -ne 2 ]; //
then
echo "error 1" 1>&2
exit 1
fi
if [ $1 -lt 0 -o $1 -gt 30 ];
then
echo "error 2"
exit 2
fi
if [ $2 -le 20 ];
then
echo "error 3"
exit 3
fi
csb@csb-ThinkPad-E430c:~/code/sh$ ./bigfiles
error 1
csb@csb-ThinkPad-E430c:~/code/sh$ ./bigfiles 40 20
error 2
csb@csb-ThinkPad-E430c:~/code/sh$ ./bigfiles 40 200
error 2
csb@csb-ThinkPad-E430c:~/code/sh$ ./bigfiles 400 20
error 2
csb@csb-ThinkPad-E430c:~/code/sh$ ./bigfiles 20 20
error 3
文件检验
-d filename 目录存在
-e filename 文件存在
-r filename 文件可读
-w filename 文件可写
-x filename 文件可执行
null命令用冒号表示,通常用于loop命令的参数来建立一个无限循环。
Case命令
case
case $* in
xx) ...
;;
xxxx)
...
;;
*)
esac
#! /bin/bash
echo "select a terminal type:"
cat <<- ENDIT
1) LINXU
2) SUN
3) XTERM
ENDIT
read choice
case "$choice" in
1) TERM=LINUX
export TERM
;;
2)TERM=SUN
export SUN
;;
3)TERM=XTERM
export TERM
;;
esac
echo "TERM IS $TERM"
csb@csb-ThinkPad-E430c:~/code/sh$ ./.bashprofile
select a terminal type:
1) LINXU
2) SUN
3) XTERM
2
TERM IS SUN
循环命令
for 变量in 清单 //每循环一次,从清单中赋值一次变量
do
commands
done
for i in @* //所用变量参数中循环
do
....
done
csb@csb-ThinkPad-E430c:~/code/sh$ cat forloop
#! /bin/bash
#sh name:forloop
for i in tom tommy cruse hanks cage
do
echo "hello $i"
done
csb@csb-ThinkPad-E430c:~/code/sh$ ./forloop
hello tom
hello tommy
hello cruse
hello hanks
hello cage
while condition
do ...
done
until condition
do
…
done
select 命令和菜单
COLUMNS=XX select菜单宽度
LINES=XX 显示的行数
select var in wordlist
do
commands
done
csb@csb-ThinkPad-E430c:~/code/sh$ cat select.sh
#! /bin/bash
#select.sh
PS3="select a program to run:"
select i in ls date gcc
do
$i
done
csb@csb-ThinkPad-E430c:~/code/sh$ ./select.sh
1) ls
2) date
3) gcc
select a program to run:2
2012年 10月 24日 星期三 21:00:11 CST
PS3(大写)用来提示用户输入
SHIFT 命令
shift [n] :用来把参量列表位移指定次数,没有参数向左位移一位
break 命令
跳出循环,跳到done当内嵌循环是,break [n] 来确定跳出的循环层数
continue命令
continue [n] 跳到第n层循环顶部执行
9.6I/O重新定向和子shell
/dev/tty 屏幕
&在后台运行循环
9.7函数
10条重要规则:
1.shell可以决定是执行一个别名/函数/内建命令,还是一个基于磁盘的可执行文件。优先级别名,函数,内建命令,可执行程序。
2.函数在使用前必须定义
3.函数在当前环境下运行,跟调用他的脚本分享变量,并通过位置参量传递参数通过local函数可以再函数内部建立本地变量(局部变量??)
4.如果你在函数中使用exit命令,则可以退出了整个脚本,如果函数退出,就返回到脚本中调用该函数的地方。
5.使用内建命令export -f可以把函数输出给子shell。
6.函数中的return命令返回函数中最后一个命令的退出状态值或者给定的参数值。
7.使用内建命令declare -f可以显示定义的函数清单,如果只显示函数的名字,可以用命令declare -F
8.像变量一样,函数内部陷阱是全局的,他们可以被脚本和脚本激活的函数共享,如果一个陷阱被定义为函数,他就可以被脚本共享,但是它可能产生意想不到的效果。
9.如果函数保存在其他的文件中,就必须通过source或dot命令把它们装入当前脚本。
10.函数可以递归,调用自己,调用次数没有限制。
格式
function function_name{ command;command;...; }({ }花括号两边的空格必须,和test [ ] 一样)
unset -f function_name 从内存中删除函数
export -f function_name 函数可以输出给子shell。
csb@csb-ThinkPad-E430c:~/code/sh$ cat funtion.sh
#! /bin/bash
function add {
local m;
let "m=$1+1"
return $m
}
echo "the m is "
add 5
echo $? #return 值保存再变量‘?’中
echo $m #函数外部m变量无效
csb@csb-ThinkPad-E430c:~/code/sh$ ./funtion.sh 52
the m is
6
csb@csb-ThinkPad-E430c:~/code/sh$
函数调用例子
csb@csb-ThinkPad-E430c:~/code/sh$ cat dbfunctions
funcion addon {
while true
do
echo "adding information $true"
echo "type thefull name of employee"
read name
echo "address"
read address
echo "$name $address"
echo -n "is it rigth"
read ans
case "$ans" in
[Yy]*)
echo "adding info"
echo $name:$address>>datefile
chmod a+x datefile
sort -u datefile -o datefile
echo -n "do you want to go back to the main menu"
read ans
if [[ $and==[Yy] ]];
then
return
else
continue
fi
;;
*)
echo "do you want to try again"
read answer
case "$answer" in
[Yy]*) continue
;;
*) exit
;;
esac
;;
esac
done
}
csb@csb-ThinkPad-E430c:~/code/sh$ cat mainprog
#! /bin/bash
#scriptname:mainprog
#it is the main script that will call funtion:addon
datefile=$HOME/code/sh/datefile
source dbfunctions #dbfuntions will load in memory
if [ ! -e $datefile ] ;#test datafile whether exit or not
then
echo "$(basename $datafile) does not exit" >&2
exit 1
fi
echo "select one:"
cat<<EOF
[1] add info
[2] delete info
[3] update info
[4] exit
[5] read datefile
EOF
read choice
case $choice in
1)addon
;; #CALL dbfuntioin
5)cat $datefile
;;
*) exit
;;
esac
echo "return"
echo "the name is $name"
csb@csb-ThinkPad-E430c:~/code/sh$ ./mainprog
dbfunctions: 行 1: funcion: 未找到命令
adding information
type thefull name of employee
csb
address
gdut
csb gdut
is it rigthy
adding info
do you want to go back to the main menuy
select one:
[1] add info
[2] delete info
[3] update info
[4] exit
[5] read datefile
5
csb:dd
csb:gdut
return
the name is csb
csb@csb-ThinkPad-E430c:~/code/sh$
陷阱信号trap
用于忽略某些signal-num,并执行‘’ “”内的命令!!
trap 被shell读取两次,一次是在设置trap时,一次是在信号到达时。
trap 'command ;command' signal-num //' '引起的命令在信号ctrl -c到达时开始执行。
Trap “command;command”signal-num//” ”引用的命令在第一次trap设置是就执行
信号复位:trap signal or num 把信号复位作为默认动作
eg:trap 2 or trap INT //为信号2,SIGINT设置默认动作
忽略信号:trap “ ” 1 2 or trap “ ” HUP int //信号1 2 被shell进程忽略
信号列表:直接输入trap显示信号列表:
csb@csb-ThinkPad-E430c:~/code/sh$ trap
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
例子:
trap 'rm tmp*;exit 1' 0 1 2 15 //0(exit) 1(hup挂起) 2(int中断) 15(term软件终止)
9.bash调试
bash -x scriptname 显示并执行脚本
set -x 跟踪脚本执行
set +x 关闭显示
getopts:命令行参数处理命令
用法:while getopts :xyn: name
解释:1.命令中 xyn都是选项,例子中x选项前面又冒号,这告诉getopts 静默错误报告,n后面有:,表示选项需要一个空格与它间隔开的参数,参数是一个没有破折号开头的单词,-n选项需要这个参数。
2.任何在命令行输入的选项都需要破折号
3.没有破折号的选项告诉getopts已经到了选项清单的末尾
4.每次调用getopts时,他都把找到的值-n 后面的参数赋值给变量name,如果给定的一个合法参数name就赋值给问号 值0
getopts函数提供了两个用于跟踪参数的变量,OPTIND:初始化1,在getopts每处理完一次命令行选项后自加1,OPTARG 变量包含合法参数的值,即用法里面的-n后面的参数!!
csb@csb-ThinkPad-E430c:~/code/sh$ cat getoptss
#! /bin/bash
#scriptname getoptss
while getopts xy opt
do
case $opt in
x)
echo you enter -x
;;
y)
echo you enter -y
;;
\?)
echo wrong
;;
esac
done
csb@csb-ThinkPad-E430c:~/code/sh$ ./getoptss -xy
you enter -x
you enter -y
csb@csb-ThinkPad-E430c:~/code/sh$ ./getoptss -b
./getoptss: 非法选项 -- b
wrong
eval命令
eval命令对命令行求值,做shell替换
csb@csb-ThinkPad-E430c:~/code/sh$ set a b c d
csb@csb-ThinkPad-E430c:~/code/sh$ echo "the last areument is \$$#"
the last areument is $4
csb@csb-ThinkPad-E430c:~/code/sh$ eval echo "the last areument is \$$#"
the last areument is d
csb@csb-ThinkPad-E430c:~/code/sh$ set -x
csb@csb-ThinkPad-E430c:~/code/sh$ eval echo "the last areument is \$$#"
+ eval echo 'the last areument is $4'
++ echo the last areument is d
the last areument is d
shell内建命令