shell是一种用C语言编写的程序,它是用户使用Linux的桥梁。shell脚本是一种使用shell编写的脚本程序。
linux系统中最常用的shell脚本解释器是Bash(Bourne Again Shell, /bin/bash)。
一个简单示例:test.sh
#!/bin/bash
echo "Hello World!"
#!声明脚本使用什么解释器解析,没有则使用默认shell。
执行
./test.sh # 会先使用指定解析器解析, 需要赋予脚本可执行权限
bash test.sh # 指明使用bash解析器解析
. test.sh # 直接使用默认解析器解析,不会执行#!指定的解析器
变量
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。单引号里的字符会原样输出,双引号可以有变量和转义字符。
#!/bin/bash
str="Hello Zhu"
readonly str
# 获取字符串长度
echo ${#str}
# 查找子字符串 lo哪个字母先出现就计算哪个
echo `expr index "$str" lo`
# 截取字符串
echo ${str:0:5}
for skill in Shell Java; do
echo "I am good at ${skill}Script"
done
# 如果在变量中使用系统命令,需要加上"`"符号
date1=`date`
date2=$(date)
# 多行注释 EOF也可以用单引号或者!代替
:<<EOF
for file in `ls C:/Users/ZHU/Desktop`; do
echo "The Desktop file : ${file}"
done
EOF
Shell 数组
#!/bin/bash
array_name=(value0 value1 value2 value3)
array_name[3]=def
# 获取数组所有元素使用@,也可通过指定索引获取指定下标数组元素
echo ${array_name[@]}
# 数组长度
echo ${#array_name[@]}
Shell 传递参数
脚本内获取参数的格式为:$n。
# 为脚本添加可执行权限
chmod +x $0
echo 执行的脚本文件名: $0
echo 第一个参数为: $1
Shell 基本运算符
# 算数运算符 + - * / % = == !=
a=1
b=2
res=`expr $a + $b`
# 关系运算符 -eq -ne -gt -it -ge -le
if [ $a -gt $b ]
then
echo "a大于b"
else
echo "a不大于b"
fi
# 布尔运算符 非运算符:! 或:-o 与:-a
if [ $a -lt 1 -o $b -gt 1 ]
then
echo "$a小于1或$b大于1:true"
fi
# 逻辑运算符 && ||
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
# 字符串运算符 = != 长度是否为0:-z 长度是否不为0:-n 字符串是否为空:$,不为空返回true
if [ $a ]
then
echo "$a : 字符串不为空"
else
echo "$a : 字符串为空"
fi
# 文件测试运算符 检测文件是否是目录:-d file 是否可读:-r file 可执行:-x 是否为空:-s file
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
Shell echo命令
# read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
read name
echo "$name It is a test"
# 显示换行
echo -e "OK! \n" # -e 开启转义
echo "It is a test"
# 显示不换行
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"
# 显示结果定向至文件
echo "It is a test" > myfile
# 显示命令执行结果
echo `date`
Shell printf 命令
# %s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。
# %-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐)
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
郭芙 女 47.99
Shell test 命令
num1=100
num2=100
if test $[num1] -le $[num2]
then
echo $num1 小于等于 $num2 成立
else
echo $num1 小于等于 $num2 不成立
fi
# Shell 还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低
cd /bin
if test -e ./notFile -o -e ./bash
then
echo '至少有一个文件存在!'
else
echo '两个文件都不存在'
fi
# 文件测试运算符
-b file (block)检测文件是否是块设备文件,如果是,则返回 true。
-c file (character)检测文件是否是字符设备文件,如果是,则返回 true。
-d file (directory)检测文件是否是目录,如果是,则返回 true。
-f file ()检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。
-p file (pipeline)检测文件是否是有名管道,如果是,则返回 true。
-r file (read)检测文件是否可读,如果是,则返回 true。
-w file (write)检测文件是否可写,如果是,则返回 true。
-x file (execute)检测文件是否可执行,如果是,则返回 true。
-s file (size)检测文件是否为空(文件大小是否大于0),不为空返回 true。
-e file (exist)检测文件(包括目录)是否存在,如果是,则返回 true。
Shell 流程控制
a=10
b=20
if [ $a == $b ]; then echo "a 等于 b"; elif [ $a -gt $b ]; then echo "a 大于 b"; elif [ $a -lt $b ]; then echo "a 小于 b"
else
echo "没有符合的条件"
fi
num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
echo '两个数字相等!'
else
echo '两个数字不相等!'
fi
# for循环
for var in item1 item2 ... itemN; do command1; command2… done;
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
# while循环
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
echo '按下 <CTRL-D> 退出'
echo -n '输入你最喜欢的网站名: '
while read FILM
do
echo "是的!$FILM 是一个好网站"
done
# until
a=0
until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
# case ... esac 多选,类似java中switch ... case
# 每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
# break
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done
# continue
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
done
<<!原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
例如,两个数相加(注意使用的是反引号 \` 而不是单引号 ')
!
val=`expr 2 + 2`
Shell 函数
#!/bin/bash
funWithReturn(){
echo "计算两个数字和"
echo "请输入第一个数字: "
read num1
echo "请输入第二个数字: "
read num2
echo "两个数字分别为 $num1和 $num2!"
return $(($num1+$num2))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
# 函数传参
funWithParam(){
echo "第二个参数为 $2 !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3
Shell 输入/输出重定向
# 输出重定向
echo "abc" > ttt
# 如果不希望内容被覆盖
echo "bcd" >> ttt
# 输入重定向,本来需要从键盘获取输入的命令会转移到文件读取内容
abc < ttt
# 统计文件行数
wc -l ttt
每个 Unix/Linux 命令运行时都会打开三个文件:
- 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
- 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
- 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
# stderr 重定向到 file
command 2>file
# stderr 追加到 file 文件末尾
command 2>>file
# 将 stdout 和 stderr 合并后重定向到 file
command > file 2>&1
command >> file 2>&1
# 对 stdin 和 stdout 都重定向
command < file1 >file2
# command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。
Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
command << delimiter
document
delimiter
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command
/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
command > /dev/null
如果希望屏蔽 stdout 和 stderr,可以这样写:
command > /dev/null 2>&1
0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。