LInux Shell 脚本笔记
*************************** list.txt : 目录 ********************************
1. variable.sh
2. condition.sh
3. control.sh
4. AndOr.sh
5.
statementBlock.sh
6. function.sh
7. command_1.sh
8.
old_version_set.sh
9. new_version_set.sh
10. command_2.sh
11.
command_3.sh
12 another.sh
13. command_4.sh
14.
command_5.sh
15. command_6.sh
16. command_7.sh
17.
command_8.sh
18. dialog.sh
************** 1 . variable.sh : start
************
#!/bin/sh
#
# Shell变量,环境变量
# 运行时带几个参数:
./variable.sh you me her him them it
echo
---------普通变量------------
myvar="Hi there!"
echo
$myvar #打印变量值
echo
"$myvar" #双引号可避免空格问题,但不抑制变量解析
echo
‘$myvar‘ #单引号抑制变量解析
echo
\$myvar #‘$‘被‘\‘转义
echo
Please enter some text:
read
myvar #键盘输入
echo
‘$myvar‘ now equals : $myvar
echo ---------环境变量------------
echo
[$IFS] #Input Field
Separator
echo ‘$0:‘ $0
#shell程序文件名
echo ‘$$:‘ $$
#进程ID
echo ‘$?:‘ $?
#最后运行的命令的结束代码(返回值)
echo
‘$*:‘$* #所有参数
echo
‘$@:‘$@ #所有参数,但不使用$IFS
echo
‘$#:‘$# #参数个数
echo args:
$1,$2,$3,$4,$5 #第1到第5个参数
set -o
verbose #在命令执行前在屏幕上回显命令
echo
‘$-:‘$-
#使用Set命令设定的Flag一览
exit 0
************** 1 . variable.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 2 . condition.sh : start
************
#!/bin/bash
#
# Shell脚本条件测试:用test或[都可
(‘[‘也是一个命令,位于/usr/bin/)
#
#字符串比较
if [ "you" = "me"
] #‘!=‘表字符串判不等
then
echo
"you = me"
else
echo "you != me"
fi
if
[ -z ""
]
#‘-n‘表不为空
then
echo "string is NULL"
else
echo "string is not NULL"
fi
#算术比较
if
test 3 -eq 4 #-ne
(这里的3,4可以是更复杂的表达式)
then
echo "3 = 4"
else
echo "3 != 4"
fi
if [ 5 -gt 6
] #-ge, -lt, -le,
!
then
echo "5 >
6"
else
echo "5 <=
6"
fi
#文件条件测试
#文件存在:通常用‘-f‘代替,因为‘-e‘可能不可移植
if test -e
fred.c; then
#then也可以放在这,但要‘;‘分隔
echo "fred.c is
exist"
else
echo "no file
fred.c"
fi
#是普通文件
if [ -f fred.c
]
#‘[‘与测试内容之间必须有空格,因为‘[‘是个命令名
then
echo "fred.c is
a general file"
else
echo "fred.c is not a
general file"
fi
# -d 是一个目录
# -r,-w,-x 文件可读,写,执行
# -u,-g
文件的SUID,SGID被设置
# -s 文件的长度不为0
exit 0
************** 2 .
condition.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 3 . control.sh : start
************
#!/bin/bash
#
#
Shell的控制语句
#
#if
echo "Is it morning? Please answer yes or
no:"
read timeofday
if [ "$timeofday" = "yes" ]
#若$timeofday不加双引号,且为空(未输入,直接按回车)的话,会产生语法错误:if [ = "yes"
]
then
echo "Good morning!"
elif [
"$timeofday" = "no" ]
then
echo "Good
afternoon!"
else
echo "Sorry, it‘s not
recognized: \"$timeofday\""
exit
1
fi
#for
for var in bar fud 45 "hehe you
sob"
#Shell认为所有变量包含的都是字符串,如这里的45
do
echo
$var
done
for file in $(ls *.sh);
do #$(cmd)
echo
$file
done
#while
foo=1
while [ "$foo" -le 20
]
do
echo -n "foo =
$foo,"
#-n是bash的echo带的去换行参数,不是所有shell都有
foo=$(($foo+1))
#$(())结构为算数扩展,替换会里面的表达式的值
done
#until
#若是该shell脚本的第一个参数指定的用户登录,则发警报
until
who | grep "$1" > /dev/null #who列出已登陆的用户
do
sleep 5
done
echo -e
\\a #响铃(我机器上没有声音?)
echo
"**** $1 has just logged in ! ****"
#case:
case结构会使用第一个匹配的模式,即使后面的模式更精确
echo "is it morning ? Please answer yes or
no:"
read timeofday
case "$timeofday" in
[Yy][Ee][Ss] | [Yy]) echo "Good
morning";;
#每个模式之后以";;"结尾,可放置多条语句
no | n)
echo "you say no or
n"
echo "Good
afternoon";;
*) echo "Soory, answer not
recognized" #*通配符匹配所有
echo "please answer yes or
no"
exit
1
;; #esac前的;;可省略
esac
exit
0
************** 3 . control.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 4 . AndOr.sh : start
************
#!/bin/bash
touch file_one
rm -f
file_two
#AND列表:&&
#[ -f file_two ]测试失败,echo "
two"不会执行
if [ -f file_one ] && echo "one" && [ -f
file_two ] && echo " two"
then
echo
"true"
else
echo
"false"
fi
#OR列表:||
rm -f file_one
if [ -f
file_one ] || echo "one" || echo "One"
then
echo
"true"
else
echo
"false"
fi
#混用AND和OR列表: 这里没有用if
#如果测试为真执行命令1,
为假执行命令2
[ -f file_one ] && echo "test for true: cmd1" || echo
"test for false: cmd2"
exit 0
************** 4 . AndOr.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 5 . statementBlock.sh : start
************
#!/bin/bash
#语句块: {}
if {
echo "We in block"
echo "You in
block"
echo "They in block"
}
then
{
echo "true"
echo "I said
true"
}
else
echo
"false"
fi
************** 5 . statementBlock.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 6 . function.sh : start
************
#!/bin/bash
#
#Shell函数
#
func()
{
echo "this"
echo
"that"
ls /bin/ls
echo
"result"
return
0
}
#直接调用函数
func
echo
"-----------------------------"
#res会捕获func()函数echo的字符串
res="$(func)"
#调用函数就跟使用其他命令一样
echo "func() executed completely:"
echo
$res
echo
"-----------------------------"
#函数内局部变量
func2()
{
local res="local
res"
#local声明局部变量
echo "Inside func2():
res=$res"
}
func2
echo "Outside func2():
res=$res"
echo
"-----------------------------"
#从函数返回一个值
yes_or_no()
{
echo "Is your name $*
?"
#这里的$*是传给函数的所有参数,不是传给shell程序的参数
while
true
do
echo -n "Enter yes or no:
"
read
x
case "$x"
in
y
| yes) return
0;;
n | no) return
1;;
*) echo "Answer yes
or no please."
esac
done
}
if yes_or_no "$1"
#调用函数并传递参数,根据return值判断执行成功还是失败
then
echo "Hi,
$1" #仅当return 0时执行这句
else
echo "Who
you are"
fi
exit 0
************** 6 . function.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 7 . command_1.sh : start
************
#!/bin/bash
#
#
Shell命令
#
#命令1:"break"
echo
----------------break----------------
rm -rf fred*
echo >
fred1 #new file
echo > fred2
mkdir
fred3 #new directory
echo > fred4
for
file in fred*
do
if [ -d "$file" ];
then
break;
#是目录则跳出
fi
done
echo I got a directory:
$file
rm -rf fred*
#命令2:"continue"
echo
---------------continue--------------
rm -rf fred*
echo >
fred1 #new file
echo > fred2
mkdir
fred3 #new directory
echo > fred4
for
file in fred*
do
if [ -d "$file" ];
then
continue;
#是目录则马上进入下一次循环
fi
echo I got a
file: $file
done
rm -rf fred*
echo
---------------:-------------------
#命令3:":"
//一个空命令,相当于true
if [ -f fred ]; then
:
else
echo "file fred did not
exist"
fi
echo
-------------.---------------------
#命令4:"."
//在当前shell中执行命令,而不是在子shell中执行(正如source命令,会改变当前环境)
echo 请在shell下用".
./old_version_set.sh",".
./new_version_set.sh"来查看效果
exit 0
************** 7 .
command_1.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 8 . old_version_set.sh : start
************
#!/bin/bash
version=Old_version
PS1="Old>
"
PATH=/bin:/usr/bin:/usr/local/Old_bin:.
************** 8 .
old_version_set.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 9 . new_version_set.sh : start
************
#!/bin/bash
version=New_version
PS1="New>
"
PATH=/bin:/usr/bin:/usr/local/New_bin:.
************** 9 .
new_version_set.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 10 . command_2.sh : start
************
#!/bin/bash
#
#
shell命令
#
echo
------------echo----------------
#命令5:"echo"
#不换行显示
echo -n
"string to output." #-n代表不输出换行
echo -e "string
to output.\c" #开启转义,\c代表结束输出(请看:man
echo)
echo #换行
echo
------------eval--------------
#命令6:"eval"
//对参数求值:像另一个$,它给出一个变量的值的值
foo=10
x=foo
y=‘$‘$x
#y=‘$foo‘
echo $y
eval y=‘$‘$x
#y=$foo=10
echo $y
echo
------------exec-------------
#命令7:"exec"
//exec命令在执行时会把当前的shell进程关闭,然后换到后面的命令继续执行。
#如:"exec touch
afile"
//会关闭shell,并创建文件afile.
echo
-------------exit-------------
#命令8:"exit"
exit 0 #成功
exit
1 #
1-125表错误码
#126表文件不可执行,127表命令未找到,128及以上表出现一个信号
************** 10 .
command_2.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 11 . command_3.sh : start
************
#!/bin/bash
#
# shell命令
#
echo
-------------export--------------
#命令9:"export"
foo="The first
var"
export bar="The second var" #被导出
foo12="The 1.5th
var"
#或set -allexport,表示导出后面声明的所有变量
set -a
foo2="The
third var" #被导出
bar2="The fourth var"
#被导出
./another.sh
#调用另一个shell脚本,它只能看见导出的bar变量,而看不到foo
echo
-----------expr------------
#命令10:"expr"
//将它的参数作为一个表达式来求值
x=3
echo "$x"
x=`expr $x +
1` #可替换为$((...))语法,更有效
echo "$x"
x=$(expr $x
+ 1)
echo "$x"
echo
-------------printf------------
#命令11:"printf"
//较新的版本shell提供该命令产生格式化输出,用来代替echo
y="you are not you."
printf
"%s:x=%d,y=\"%s\"\n" "info" "$x" "$y"
#$y要用""包围
echo
-----------set--------------
#命令12:"set"
//为shell设置参数变量,就像脚本的参数(命令9用法不太一样)
set $(date)
#设置参数为date命令的输出(空格分隔的)
echo $0,$1,$2,$3
set 1 "go you" 5000
echo
$1,$2,$3
echo
-----------shift-----------
#命令12:"shift"
//将所有的参数变量左移一个位置:$2变为$1...,注意$0不变
while [ "$1" != "" ];
do
echo "$1"
shift
done
exit 0
************** 11 . command_3.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 12 . another.sh : start
************
#!/bin/bash
echo "$foo"
echo "$bar"
echo
"$foo12"
echo "$foo2"
echo "$bar2"
************** 12 .
another.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 13 . command_4.sh : start
************
#!/bin/bash
#
# shell命令
#
echo
--------------unset---------------
#命令14:"unset"
//从环境中删除变量或函数,但不能删除shell本身定义的只读变量如PATH
foo="Oh I‘am here"
echo
$foo
foo=
#将foo设为空,变量仍存在
echo $foo
foo="Oh i am here again"
echo
$foo
unset foo #将foo变量删除掉
echo $foo
echo
--------------trap------------------
#命令15:"trap"
# trap cmd signal:
当信号signal出现时,执行命令cmd(该命令之后有效)
# trap signal:
忽略信号signal
# trap - signal: 恢复signal的默认处理
trap ‘rm -f
/tmp/my_tmp_file_$$‘ INT #可以用trap -l看到INT信号
echo
createing file /tmp/my_tmp_file_$$
date >
/tmp/my_tmp_file_$$
echo "press CTRL+C to interrupt ..."
while [
-f /tmp/my_tmp_file_$$ ]; do
echo File
exists
sleep 1
done
echo "File no longer
exists"
#设置回CTRL+C信号的默认处理:终止程序
trap INT
echo createing file
/tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
echo "press
CTRL+C to interrupt ..."
while [ -f /tmp/my_tmp_file_$$ ]; do
echo File exists
sleep
1
done
echo "should not reach here"
************** 13 .
command_4.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 14 . command_5.sh : start
************
#!/bin/bash
#
# shell
#
echo
-----------find------------
#命令16:"find"
#find [path] [options]
[test] [actions]
find . -name fun*.sh -print
echo
-------
find / -mount -name wish
#-mount不去搜索挂载的其他文件系统
echo -------
find . -newer command_2.sh
-type f #搜索比command_2.sh要新的文件,不是目录
echo
-------
find . -newer command_2.sh -o -name "v*.sh"
#-o表示或者,-a表示并且,!表非
echo -------
find . -newer command_2.sh -or
-name "v*.sh" #-or表示或者,-and表示并且,-not表非
echo
-------
#用圆括号来组合测试(不用也是成功的)
find . \( -newer command_2.sh -o
-name "v*.sh" \) -type f -print
echo
-------
#找到匹配的文件后,可以执行指定的动作:
find . -name "c*" -exec ls -l {}
\;
#-exec或-ok命令将后续参数作为他们的参数直到被"\;"终止,魔串"{}"会被当前文件的完整路径取代
************** 14
. command_5.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 15 . command_6.sh : start
************
#!/bin/bash
#
# shell命令
#
echo
----grep: General Regular Expression Parser----
#grep [option] pattern
[files]
grep "if" ./condition.sh
echo ----------
grep -c "if"
./condition.sh ./command_1.sh #搜索多个文件,只输出匹配行数
echo
----------
grep -v "i" ./condition.sh
#匹配不出现"i"的行
echo ---------
grep ^#
./condition.sh #行首为用‘^‘,行尾用‘$‘
echo
-----------
grep [[:blank:]]echo[[:blank:]]
./condition.sh
#[]中可以使用特殊匹配模式,[:blank:]表示空格或制表符
echo ------------
grep -E
[a-z]\{5\} ./condition.sh #-E开启扩展匹配:? * + {n} {n,} {n,m}
//匹配0或1次,0或多次,1或多次,n次,n次及以上,n到m次
************** 15 . command_6.sh :
end
**************
@
@
( V
)
^
^
.=.=.0
************** 16 . command_7.sh : start
************
#!/bin/bash
#
# shell命令的执行
#
#
$(cmd)的结果就是cmd命令的输出
//只有需要脚本可移植时才应该用`cmd`(当命令中有特殊字符时要转义)
echo
‘------------$(cmd)-------------‘
echo Current user:
$(who)
whoisthere=`who`
echo Current user: $whoisthere
echo
--------------${var}------------
# 参数扩展:
${var}
//如${i}_tmp会扩展变量i,而$i_tmp会扩展变量i_tmp
for i in 1 3 5
do
echo cmd_${i}_cmd
echo
CMD_$i_CMD #$i_CMD会被扩展为空,不会报错!
done
echo
--------
# ${param:-default}
若param为空,则把扩展为default
#
${#param}
扩展为param的长度
#
${param%word}
在param的尾部删除与word匹配的最短串,返回剩余部分
#
${param%%word} 尾部,删最长匹配
#
${param#word}
头部,删最短匹配
# ${param##word}
头部,删最长匹配
unset foo
echo ${foo:-hello you} #foo为空,扩展为hello
you
foo=something
echo
${foo:-Hello}
#foo不为空,扩展为something
foo=/usr/bin/X11/startx
echo
${foo#*/}
#删去头部/
echo ${foo##*/}
#删去头部/usr/bin/x11/
bar=/usr/local/etc/local/networks
echo
${bar%local*} #删去尾部local/networks
echo
${bar%%local*}
#删去尾部local/etc/local/networks
echo ‘-----example for ${
}------‘
touch 1.gif 2.gif 3.gif
ls *.gif *.jpg
for image in
*.gif
do
mv $image
${image%%gif}jpg #效果如: mv 1.gif
1.jpg
done
ls *.gif *.jpg
rm *.jpg
#另外:
#
${param:+default} 若param不为空,则返回default
#
${param:=default}
若param为空,则赋值为default,再返回;否则直接返回param的值
#
${param:?default} 若param为空,则输出param:
default;否则返回param
************** 16 . command_7.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 17 . command_8.sh : start
************
#!/bin/bash
# <<TAG 和
TAG中间的内容就好象是标准输入的内容
echo
‘--------------<<TAG--------------‘
cat
<<!SomeText!
hello you little boy.
hello you boy.
hello
you.
hello.
!SomeText!
echo -------------
echo "hello."
> hei.txt
echo "hello you." >> hei.txt
echo "hello you
boy." >> hei.txt
echo "hello you little boy." >>
hei.txt
cat ./hei.txt
echo
-------------
#用ed编辑文件hei.txt,编辑命令为1,d,2,...
#
下面的‘$‘用‘\‘转义,为了防止shell对其做解释,因为要解释它的应该是ed
ed ./hei.txt
<<!SomeOperations!
1
d
2
\$s/you/me/
w
q
!SomeOperations!
cat
./hei.txt
rm ./hei.txt
#调试shell程序
# set -o noexec, 简写set -n,
命令行sh -n foo.sh
//只检查语法,不执行
# set -o verbose, 简写set -v, 命令行sh -v
foo.sh //执行命令前先回显
# set -o
xtrace, 简写set -x, 命令行sh -x
foo.sh //执行命令后回显
# set
-o nounset, 简写set
-u
//若使用了未定义的变量,给出出错信息
echo ‘----------set -v---------‘
set
-v
ls
set +v
#+v表示关闭verbose选项
echo ‘----------set -u---------‘
set
-u
#echo $nodefine #使用了为定义的变量,给出错误信息
#捕获退出信号,输出变量值
echo
------------trap handler signal-----------
foovar="i‘m something
important."
trap ‘echo Exiting: foovar= $foovar‘
EXIT
************** 17 . command_8.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 18 . dialog.sh : start
************
#!/bin/bash
#dialog命令:
linux控制台下的简单GUI程序
#对话框
标题
消息框
dialog --title "Message you" --msgbox "Tell you something you do
not know." 8 40
if [ $? = 0 ]; then
dialog
--infobox "your choose: OK" 5 20
sleep
1
dialog --clear
fi
#对话框
标题
复选列表 提示
高 宽 选项数
选项编号,文本,状态....
标准错误重定向(dialog的输出)
dialog --title "Check box example" --checklist "Pick
Number" 15 25 3 1 "one" "off" 2
"two" "on" 3 "three" "off" 2>
/tmp/tmp_file_$$.txt
ret=$?
#保存dialog的返回值
res=$(cat
/tmp/tmp_file_$$.txt)
#保存dialog的输出值(用户选择的选项)
if [ $ret = 0 ]; then
dialog --infobox "Your choise: $res" 10 30
else
dialog --infobox "Bad, you canceled!" 10 30
fi
echo
"$res"
#
************** 18 . dialog.sh : end
**************
@
@
( V
)
^
^
.=.=.0
************** 19. merge.sh : 合并list.txt中列出的当前目录下的文件 **************************
#!/bin/bash
if [ -f list2.txt ]
then
rm
-f list2.txt
fi
cat ./list.txt | while read
line #读取list.txt的每一行
do
echo
${line#*[[:blank:]]} >> list2.txt
#去掉行首的序号和空白字符
done
x=0
#文件序号
if [ -f merged.txt ]
then
rm -r
merged.txt
fi
cat ./list2.txt | while read
line
do
x=$(($x + 1))
echo
"************** $x . $line : start ************" >>
merged.txt
cat ./$line >>
merged.txt
echo "************** $x . $line : end
**************" >> merged.txt
echo
"
" >> merged.txt
echo
"
@
@
" >> merged.txt
echo
"
( V
)
" >> merged.txt
echo
"
^
^
" >> merged.txt
echo
"
.=.=.0
" >> merged.txt
echo
"
" >> merged.txt
done
if [ -f list2.txt
]
then
rm -f
list2.txt
fi
*********************************** End ***********************************