开头
#! /bin/bash
#! /bin/sh
执行shell脚本
- . a.sh
- chmod +x a.sh ./a.sh
- /bin/sh ./a.sh
- source ./a.sh
变量
1.环境变量
环境变量可以从父进程传给子进程,因此Shell进程的环境变量可以从当前Shell进程传给fork出来的子进程。用printenv命令可以显示当前Shell进程的环境变量
2.本地变量
a=10
b=20
等号两边都不能有空格,否则会被Shell解释成命令和命令行参数
shell变量的值都是字符串
通过刀了符取变量的值$a
文件名代替
wildcard通配符
代表0个或多个 如:.c 当前目录下所有的.c文件
?代表0个或1个 如:ami?.c 目录下有amid.c则匹配amid.c文件
[若干字符]方框内任意一个字符出现1次 如 ami[0-9][2-3].c,目录下有amid12.c文件
命令代替
Date=$(date) #先执行date
echo $(Date)
或
Date=date
Shell先执行该命令,然后将输出结果立刻代换到当前命令行中
算术代换
$(())或[]
两个数求和
#! /bin/bash
a=10
b=20
echo "a+b=$(($a+ $b))"
#echo "a+b=$[$a+$b]
转义字符
\
创建特殊字符文件 -a.c # #a.c
touch -a.c
写成touch ./-a.c 或 touch – -a.c
touch $ #a.c
转义
touch #\ #a.c
单引号 双引号
echo ‘hello world “hello world”’
双引号引的是一条命令,能将它展开变量
单引号不能展开变量
条件测试
[ -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(大于等于)之中的一个
[ ! EXPR ] EXPR可以是上表中的任意一种测试条件,!表示“逻辑反(非)”
[ EXPR1 -a EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-a表示“逻辑与”
[ EXPR1 -o EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-o表示“逻辑或”
分支
if/then/elif/fi
1 #! /bin/sh
2
3 echo "is this zhangyu? please answer yes or no"
4
5 read YES_OR_NO
6 if [ "$YES_OR_NO" = 'yes' ]
7 then
8 echo "he is"
9 elif [ "$YES_OR_NO" = 'no' ]
10 then
11 echo "he is not"
12 else
13 echo "sorry, i don't know"
14 fi
case/esac
1 #! /bin/sh
2
3 echo "is this zhangyu? please answer yes or no"
4
5 read YES_OR_NO
6
7 case "$YES_OR_NO" in
8 yes|YES|Yes|y|Y)
9 echo "yes,he is";;
10 [Nn]?)
11 echo "no,he is not";;
12 *)
13 echo "sorry i don't know";;
14 esac
循环
for/do/done
编译当前文件下的所有.c文件
1 #! /bin/bash
2
3 for exe in `ls *.c` ;do
4 gcc $exe -o ${exe%%.*}
5 done
将一目录下所有的文件的扩展名改为bak
1 #! /bin/sh
2
3 for filename in *.* ;do
4 mv $filename ${filename%%.*}.sh
5 done
while/do/done
求1-100的和
1 #! /bin/sh
2 i=1
3 sum=0
4 while [ $i -le 100 ]; do
5 sum=$[$sum+$i]
6 i=$(($i+1))
7 done
8 echo "1~100的和为$sum"
介绍下Shell中的${}、##和%%使用范例,本文给出了不同情况下得到的结果。
假设定义了一个变量为:
代码如下:
file=/dir1/dir2/dir3/my.file.txt
可以用${ }分别替换得到不同的值:
${file#*/}:删掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:删掉最后一个 / 及其左边的字符串:my.file.txt
${file#*.}:删掉第一个 . 及其左边的字符串:file.txt
${file##*.}:删掉最后一个 . 及其左边的字符串:txt
${file%/*}:删掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:删掉第一个 / 及其右边的字符串:(空值)
${file%.*}:删掉最后一个.及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:删掉第一个.及其右边的字符串:/dir1/dir2/dir3/my
记忆的方法为:
#是去掉左边(键盘上#在 $ 的左边)
%是去掉右边(键盘上% 在$ 的右边)
单一符号是最小匹配;两个符号是最大匹配
${file:0:5}:提取最左边的 5 个字节:/dir1
${file:5:5}:提取第 5 个字节右边的连续5个字节:/dir2
也可以对变量值里的字符串作替换:
${file/dir/path}:将第一个dir 替换为path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:将全部dir 替换为 path:/path1/path2/path3/my.file.txt
break和continue
break[n]可以指定跳出几层循环;continue跳过本次循环,但不会跳出循环。
即break跳出,continue跳过。
位置参数和特殊变量
$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
$$当前进程号
位置参数可以用shift命令左移。比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1、$2、$3丢弃,$0不移动。不带参数的shift命令相当于shift 1。
输入输出
echo
管道
文件重定向
cmd > file 2>&1 标准出错也重定向到1所指向的file里
tee
tee命令把结果输出到标准输出,另一个副本输出到相应文件