- 数据类型、变量
- 分支语句、循环语句
- 函数
数据类型、变量
- shell中仅有一种数据类型:字符串
- 变量类型仅有两种:环境变量、本地变量
VAR=123 #定义一个本地变量VAR,值123(字符串)
export VAR #把VAR导出为环境变量
//上述两步可合并为一步:
export VAR=123
//除了 echo $VAR 外,还可以用如下方式查看该环境变量的值:
env | grep VAR
- 自建一个命令别名:
alias,比如:
alias pg='ps aux | grep'
pg init #等同于 ps aux | grep init
- 删除一个变量:
unset - 通配符(wildcard):
*:匹配0个或多个任意字符
?:匹配一个任意字符
[若干字符]:匹配方括号中任意一个字符的一次出现 - 命令代换:显示命令本来的功能而不是作为一个字符串显示出来
反引号 ``:
var=`date`
echo $var //执行date命令
$( ):
var=$(ls)
echo $var //执行ls命令
- 算术代换:
VAR=1
echo $[VAR+3] //4
echo $[2#10+8#76] //2进制10加8进制76,结果为64
- 转义字符:
反斜杠\:续行;转义
touch \$\ \$test.sh //创建一个名为’$ $test.sh’的新文件
touch ./-abc //创建一个名为’-abc’的新文件,或:touch -- -abc
rm ./-abc //删除该文件,或:rm -- -abc
- 单、双引号:
- 单双引号可嵌套使用:
echo 'hello "xiao"' //hello "xiao"
echo "hello 'xiao'" //hello 'xiao'
- 双引号:被双引号用括住的内容,将被视为单一字串,它防止通配符扩展,但允许变量扩展。这点与单引号不同。例如:
VAR=`date`
echo '$VAR' //$VAR
echo "$VAR" //执行date命令的结果
- 注意:
var= //定义变量var,初值为Null,常用于if条件判断语句中
echo ‘$var’ //$var
echo “$var” //为空,即Null
//区别于:
var=Null //定义变量var,初值为字符串Null
语句
条件测试
- test、[
[ -d DIR ] 如果DIR存在并且是一个目录则为真
[ -f FILE ] 如果FILE存在且是一个普通文件则为真
[ -z STRING ] 如果STRING的长度为零则为真
[ -n STRING ] 如果STRING的长度非零则为真
[ STRING1 = STRING2 ] 如果两个字符串相同则为真
[ STRING1 != STRING2 ] 如果字符串不相同则为真
[ ARG1 OP ARG2 ] ARG1和ARG2应该是整数或者取值为整数的变量,OP是-eq(等于)-ne(不等于)-
lt(小于)-le(小于等于)-gt(大于)-ge(大于等于)之中的一个
例如:
var=10
test $var -gt 20 //gt: greater than
echo $? //1,表示上述比较结果为假;echo $? //输出上一条命令的返回值
[ $var -lt 20 ] //lt: less than
echo $? //0,表示上述比较结果为真
- 测试条件之间还可以做与、或、非逻辑运算:
[ ! EXPR ] EXPR可以是上表中的任意一种测试条件,!表示逻辑反;
[ EXPR1 -a EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-a表示逻辑与;
[ EXPR1 -o EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-o表示逻辑或。
var=abc
[ -d Desktop -a $var = 'abc' ] //Desktop是否是一个目录,并且,var的值是否等于abc
echo $? //0,真
- 建议:应总是把变量取值放在双引号之中,这是一种好的shell编程习惯。所以上述例子中,作为一种好习惯,应写为:
[ -d Desktop -a "$var" = 'abc' ]
因为,如果上例中的$var变量事先没有定义,则被Shell展开为空字符串,会造成测试条件的语法错误(展开为[ -d Desktop -a = ‘abc’ ])。
分支
if语句:
例如:
#! /bin/sh
echo "Is it morning? Please answer yes or no."
read var
if [ "$var" = "yes" ]; then
echo "Good morning!"
elif [ "$var" = "no" ]; then
echo "Good afternoon!"
else
echo "Sorry, $var not recognized. Enter yes or no."
fi
注意:
if :
then
echo "always true"
fi
其中,if : 中的冒号表示条件总是为真
case语句:
#! /bin/sh
echo "enter YES or NO"
read var
case "$var" in
YES|Yes|Y|yes|y)
echo "good!"
;; #similar to break in C\C++
[nN]*) #a string beginning with n or N
echo "bad!"
;;
*) #similar to default
echo "invalid input! enter YES or NO please."
;;
esac
echo "will return"
return 0
循环
for-do-done:
#! /bin/bash
for MYFILE in $(ls); do
printf "$MYFILE "
if [ -d "$MYFILE" ]; then
echo "it's a directory."
elif [ -f "$MYFILE" ]; then
echo "it's a file."
else
echo "others."
fi
done
while-do-done:
#! /bin/bash
count=2
echo "Please enter the password: "
read psd
while [ $psd != "myword" -a $count -gt 0 ]; do
count=$[count-1]
echo "wrong! enter again:"
read psd
done
if [ $psd = "myword" ]; then
echo "good!"
fi
if [ $count -eq 0 ]; then
echo "you have entered wrong password three times."
fi
break:
和C语言中的不同之处在于,break[n]可以指定跳出n层循环。continue:同C语言中用法
特殊变量
$0 相当于C语言main函数的argv[0],表示当前进程名
$1、$2... 这些称为位置参数(Positional Parameter),相当于C语言main函数的argv[1]、argv[2]...
$# 相当于C语言main函数的argc - 1,即去掉函数名的参数个数,注意这里的#后面不表示注释
$@ 表示参数列表"$1" "$2" ...,例如可以用在for循环中的in后面。
$* 表示参数列表"$1" "$2" ...,同上
$? 上一条命令的Exit Status
$$ 当前进程号
输入输出
echo
echo [option] string
-e 解析转义字符
-n 不回车换行。默认情况echo回显的内容后面跟一个回车换行。
echo "hello\n\n"
echo -e "hello\n\n"
echo "hello"
echo -n "hello"
管道|tee:
tee命令把结果输出到标准输出,另一个副本输出到相应文件。- 文件重定向:
cmd > file 2>&1 //标准出错也重定向到1所指向的file里
cmd < file1 > file2 //输入输出都定向到文件里
函数
- 注意位置参数在函数内外的区别:
#! /bin/bash
echo $1 //命令行输入的第一个参数
echo $2
echo $3
func() {
echo $1 //该函数被调用时紧跟着的第一个参数
echo $2
echo $3
}
echo -e "---func start---\n"
func 1 2 3
echo -e "---func end---\n"
//执行:
chmod a+x funcdemo.sh
funcdemo.sh a b c
//执行结果:
a
b
c
---func start---
1
2
3
---func end---
//注意:位置参数$1、$2、...位于函数外则表示从命令行接收的参数;
//位于函数内则表示函数被调用时紧跟着的参数
//$0在函数内外没有区别,均表示当前进程名
- 另一个例子:
#输入一些命令行参数代表文件名,如果不存在则创建这些文件
#! /bin/bash
is_file() {
FILE_NAME=$1
if [ ! -f $FILE_NAME ]; then
return 1
else
return 0
fi
}
for file in "$@"; do
if is_file "$file" #is_file 返回0表示真,返回1表示假
then : #do nothing
else
echo "$file doesn't exist. Creating it now..."
touch $file > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Can't create file $file"
exit 1
fi
fi
done
脚本调试
-n
读一遍脚本中的命令但不执行,用于检查脚本中的语法错误-v
一边执行脚本,一边将执行过的脚本命令打印到标准错误输出-x
提供跟踪执行信息,将执行的每一条命令和结果依次打印出来- 使用方法有三种:
- 在命令行提供参数
$ sh -x ./script.sh
- 在脚本开头提供参数
#! /bin/sh -x
- 在脚本中用set命令启用或禁用参数
#! /bin/sh
if [ -z "$1" ]; then
set -x
echo "ERROR: Insufficient Args."
exit 1
set +x
fi
正则表达式
常用工具
grep
- grep侧重于过滤文件中的内容,而find侧重于根据文件名、文件类型、文件修改时间来找文件。
- grep、egrep
本文介绍了Shell编程的基础知识,包括数据类型与变量、分支和循环语句、条件测试、函数、脚本调试,以及常用的正则表达式和工具如grep、find、sed和awk。特别强调了在条件测试中的逻辑运算和脚本调试方法。

9113

被折叠的 条评论
为什么被折叠?



