Shell编程——基于IBM培训教程的总结
第一章 shell基础
1. file 命令可以查看文件类型
2. 如果需要查看普通文件内容,使用cat命令,如果需要查看二进制文件内容,使用string命令(AIX特有命令)。
3. 以“.”开头的文件是隐藏文件,需要使用ls -a的方式查看。
4. 在shell脚本文件的头一行使用类似于“#!/bin/ksh”的方式来告诉当前shell使用另外一个shell来执行这个脚本。
如果prog是一个shell脚本文件,已经使用了chmod +x prog的方式拓展了执行权限。如果当前shell是ksh,而prog首行内容是
#!/bin/tsh
则exec prog
将会停止ksh并且启动tsh这个shell并执行prog
5. 如何设置shell?没看明白!通过.profile, .exrc, $ENV等
6.SHELL的元字符与正则表达式类似,但不完全相同。例如
* 表示零个或者多个字符;
?表示一个字符;
[abc]表示a,b,c中任意选择一个
[!abc]表示a,b,c中一个都不选(正则是[^abc])
[a-z]
举例:
ls [a-z]c.c
上面的语句将会选择出ac.c,gc.c等
7.SHELL特殊的元字符
*(pattern1|pattern2) 0次或者多次触发
例如,*([0-9]) 0个或者多个数字
?(pattern1|pattern2) 0次或者1次触发
例如,?([0-9]) 0个或者1个数字
+(pattern1|pattern2) 1次或者多次触发
@(pattern1|pattern2) 仅仅1次触发
!(pattern1|pattern2) 1次都不触发
例如,!(err*|fail*)表示,不能以“err”或者"fail"开头的词
举例:
ls [a-z]*t[0-9]
8. 关于引号
i) 双引号("")
双引号表示转平凡字符串,但是除了“$”,“`”,“\”
例如,echo "abc`date`"
ii)单引号('')
相当C#中的@""效果
iii)反斜杠(\)
只平凡化(\)之后一个单词,例如 \`date`
9. 关于重定向
i) "1>" 等价于 ">" 标准输出
"0<" 等价于 "<" 标准输入
ls > abc.txt
ls < abc.txt
ii)"2>" 错误输出重定向
ls 2> abc.txt
10. 重定向连结
如 ls > file 2>&1
表示将ls标准输出输出至file,错误输出输出在标准输出上
11. 文件描述符
0 表示标准输入
1 表示标准输出
2 表示错误输出
3-9自定义使用
例如 exec 3> /home/lee/out (把3号文件描述符打开为文件)
例如 exec 3> &- (把3号文件描述符关闭)
12. pipe中的暂存功能
例如, cat a.txt | tee b.txt | sort -r
关键字是tee.
上面的语句的含义是,先把a.txt中内容存储到b.txt,然后逆序排列a.txt中的内容。
13. jobs, bg, fg
14. 重复命令(暂存命令)
例子:
d=$(date)
echo $d
第二章 参数与引用
1. 参数设定与取消
# name=abc (设定)
# unset name (取消)
# readonly name=abc (不可unset或者改变)
2. 引用参数
使用“$”
# var1=Fri
# echo $var1 (打印Fri)
# echo ${var1}day (Friday)
3. 引用SHELL脚本的参数
# abc.sh arg1 arg2
用 $1 到 $9
用 ${10} to ${n}
4. 在script中用set可以转换调用参数
print $1 $2 $3
set apple banana
print $1 $2 $3 // 打印出apple banana
5. 特殊符号
$# 位置参数个数
$@ 用空格分割的位置参数
$* 用指定占位符分割位置参数
$0 命令名
$$ 当前PID
$! 最近背景进程的PID
$? 最近执行语句的返回值(0表示成功)
6. shift
shift n
原来的$m变成$m-n
7. 有用的环境变量
i) ERRNO
ii)CDPATH
iii)HOME
iv) PATH
v) ENV
第三章 返回值与信号陷阱
1)测试
使用test expression语句,返回0表示expression为真(true),返回非零(false)表示为假。
当作用在if语句中时,完全可以按照字面意思去理解。
i) 文件测试
test -s file
test -r file
....
ii)数字测试
test 1 -ne 2
test 1 -eq 2
test 1 -lt 2
test 1 -le 2
test 1 -gt 2
test 1 -ge 2
iii) 字符串测试
test -n str str is non-zero in length
test -z str str is zero in length
test str1 = str2
test str1 != str2
2) 与,或,非, 组合(括号的概念)
test exp1 -a exp2 与
test exp1 -o exp2 或
test !exp 非
\( exp \) 注意空格 (在shell script中也需要有斜杠“\”)
test \( 1 -ge 2 \) -a 1
3) 信号
i) 发送信号
kill -s sig pid
ii)列出所有信号
kill -l
4)在shell中重定向信号处理方式
i) 指定处理方式
以下代码表示,当有SIGINT或者SIGQUIT信号的时候,做指定的事情
trap ‘rm /tmp/$$’ SIGINT SIGQUIT
ii) 忽略信号
trap '' SIGINT SIGQUIT
iii) 恢复信号
trap SIGINT SIGQUIT
第四章 跳转语句
1) if - else - elif - fi
例如
if [ \( 1 -le 2 \) -a \( 2 -gt 1 \) ]
then
echo "hello world"
elif [ 3 -le 4 ]
echo "hello two"
else
echo "faint"
fi
2) 循环语句
x=0
while [ $x -lt 2 ]
do
echo $x
let x=x+1
done
while true
do
echo "hello"
continue
done
until [ $x -gt 5 ]
do
echo $x
let x=x+1
break
done
3) for 语句
下面的语句将会便利所有在pwd文件夹下以单个数字作为拓展名的文件
for file in *.[0-9]
do
echo $file
done
下面的两个语句效果相同,不过更推荐第二种写法
for file
do
done
for file in $@
do
done
类似C语言的做法
for (( num=0; num < 5; num++ ))
do
echo $num
done
4) case语句
x=0
case "this is $1 $x" in
"this is 1")
echo "hello 0";;
"this is 1 0")
echo "hello 1";;
*)
echo "hello 10";;
esac
case语句中还可以放置命令,例如
case $(ls) in
0)
echo "hello 0";;
1)
echo "hello 1";;
*)
echo "hello 10";;
esac
5) select关键字
在shell编程中,为了展示一段memu以供客户选择,可以使用select关键字,网上查吧。
6)null语句
当在调试时,对于一个空的if, while, for等block的处理,可以使用null语句(":")。方法是:
if [ 1 -le 2 ]
then
# debug only, using null statement
:
else
echo "hello"
fi
第五章 shell命令
1. 从标准输入中读入内容放入变量
#read x y z
1 2 3
#echo $x $y $z
输出“1 2 3”
关于read的相关参数
read -a variable ;读入array,index从0开始
例如,
#read -a name
Lee Lynn Llewellyn
上面的语句将会先unset数组变量name,然后将name[0]设置为Lee,name[1]设置为Lynn,name[2]设置为Llewellyn
read -s ;no echo模式
read -p "string " variables ;标准输入上给出一定的提示(string),然后和不带参数的read一样。
例如:
read -p "here is your name " var1 var2
注意:
i. 如果变量少于输入,则最后一个变量将会包含后续的所有输入
ii.如果输入少于变量,则多出来的变量就会变为空
iii.如果没有指定变量,则bash会把变量存在$REPLY中
2. 获取参数与开关
有下面的这个例子
USAGE="usage: example.getopts.sh [+-c] [-a argument] arg1 arg2 ..."
while getopts :a:cv varflag
do
case $varflag in
a) argument=$OPTARG;;
c) compile=on;;
+c) compile=off;;
:) echo "you forgot an argument for the switch called a.";
exit;;
?) echo "$OPTARG is not a valid switch"; echo $USAGE; exit;;
esac
done
shift $(( $OPTIND - 1 ))
上面的语句几乎包含了所有的知识点
1) USAGE中定义的用法是 option + arguments
2) 试用getopts方法来获取所有的option
3) getopts第一个参数是表示你需要获取的option的种类。其中第一个":"表示你要自己来控制错误信息(例如这里的\?) ),"a"后面的“:”表示"-a"后面需要有参数。c与v后面没有“:”表示不需要有arguments
4) [+-c]表示c这个option是可选的,而"-c"习惯上表示指定c这个option,"+c"习惯上表示不指定这个option.(bash好像不支持"+")
5) OPTARG中保存着option之后的argument,例如-a后面的那个。
6) OPTIND是在处理过的option的个数,通过shift OPTIND就可以跳过所有的OPTION以进入到真正的arg1,arg2等。
7) 如果出现了没有希望处理的option(这里是"acv"之外的option),则会返回“?”
第六章 算数操作命令
1. let 操作符及其简写形式(( expr ))
限制:只能够处理成整数
a=5
b=3
let c=a/b d=a+b
#上句等价于 (( c = a / b )); (( d = a + b ))
echo $c $d #输出1 8
特点,
i) 速度快
ii)变量不需要使用$
iii) 这个语法可以用在if, while中。(这个要比之前的语法方便多了)
p=10
q=20
if (( (p < q && p ==54) || ( 2 > 1 ) ))
then
echo "hello"
fi
while (( p < q ))
do
echo "$p"
(( p = p + 1 ))
done
iv) 注意区别下面的语句(关键的区别在于“(())”返回的是变量)
q=$(( p * 3 ))
(( q = p * 3 ))
2. 各种进制下的数值表示
i) 2进制下的100 : 2#100
ii)8进制下的33 : 8#33
第七章 SHELL数组,命令和函数
1. SHELL数组
i) 数组的定义
方法一:
list[0]=1
list[1]="123"
list[3]=4
此时,list[2]会被自动配置为null。此时,如果使用${#array[*]}的方式令其返回数组元素的个数,则会返回2。因为list[2]==null,它被认为是表示数组结束的标志。但是,如果使用${list[*]}则会返回4个值,其中list[2]返回空值。
方法二:
set +A list 1 "123" 2 4
此时,整个list将会被赋予4个值。
ii) 数组的操作
-赋值: array[N]=argument
-打印某个元素:echo ${array[N]}
-遍历所有的元素,用空格隔开:${array[*]}或者${array[@]}
-此二者等价: ${array[0]} == $array
-数组中有多少元素:${#array[*]}或者${#array[@]}
2. 函数
下面是一个函数的例子
function EmbededFunc()
{
echo $b #输出5,因为b在上级调用函数中的全局变量
echo "in EmbedFunc $a" #输出3,因为a在上级调用函数中被定义
}
function Func()
{
b=5
local a=3
echo $1
EmbededFunc
return 0
}
Func abc
echo “in main script $a“ # 输出空值,因为a是local的
echo “in main script $b“ # 输出5,因为b是global
注意:
1) $0无论在函数内还是在函数外都表示本脚本的名字
2) $1 - ${N},表示传输的参数
3) 在function中可以使用“return N”的方式从func中返回一个值,或者使用“exit N”退出整个script。
4) 没有被指定为local的变量都是全局变量,也就是在此定义之外的所有地方都会有用到。
5) 被定义为local或者typeset的变量是局部变量,出了作用域就没有作用了。
6) 可以强行使用"unset -f function_name"的方式将函数从内存中卸除。
7) 上级函数中定义的local对于其调用的函数都是全局变量。
3. alias —— linux shell的#define
例如,在shell中,打命令alias,看到常用命令的别名。
-自定义alias:
alias px="echo $x"
-使用alias
x=100
px
-撤销alias
unalias px
第八章 SHELL变量(续)
1. 子字符串
1) 截取要求中的“最左”与“最右”
注意:pattern只能是从最左开始匹配,如果不包含第一个字符,那么就不能工作。
${variable#pattern} - 截去从最左开始匹配的最短符合pattern的子串
${variable##pattern} - 截去从最左开始匹配的最长符合pattern的子串
${variable%pattern} - 截去从最右开始匹配的最长符合pattern的子串
${variable%%pattern} - 截去从最右开始匹配的最长符合pattern的子串
例如:
variable="Now is the time"
echo ${variable} // 打印出 Now is the time
echo ${variable#N*i} // 打印出 s the time
echo ${variable##N*i} // 打印出 me
echo ${variable%time} // 打印出 Now is the
echo ${variable%%t*e} // 打印出 Now is
再例如
echo ${1#*\} 表示了找到第一个参数所表示的文件全路径的文件名
2)子串
语法:${variable:offset:length}
例如:
var="hello"
var=${var:3:2}
echo $var //打印出 "lo"
2. 变量长度
例如,找到var变量所包含的长度
${#var}
3. 替换
语法:${variable/pattern/newpattern}
将variable中第一个匹配的pattern替换为newpattern
例如:
var="hello world"
var=${var/l/X}
echo $var # 输出 heXlo world
语法:${variable//pattern/newpattern}
将variable中所有匹配的pattern替换为newpattern
例如:
var="hello world"
var=${var//l/X}
echo $var # 输出 heXXo worXd
第八章 SHELL变量(续)
1. 子字符串
1) 截取要求中的“最左”与“最右”
注意:pattern只能是从最左开始匹配,如果不包含第一个字符,那么就不能工作。
${variable#pattern} - 截去从最左开始匹配的最短符合pattern的子串
${variable##pattern} - 截去从最左开始匹配的最长符合pattern的子串
${variable%pattern} - 截去从最右开始匹配的最长符合pattern的子串
${variable%%pattern} - 截去从最右开始匹配的最长符合pattern的子串
例如:
variable="Now is the time"
echo ${variable} // 打印出 Now is the time
echo ${variable#N*i} // 打印出 s the time
echo ${variable##N*i} // 打印出 me
echo ${variable%time} // 打印出 Now is the
echo ${variable%%t*e} // 打印出 Now is
再例如
echo ${1#*\} 表示了找到第一个参数所表示的文件全路径的文件名
2)子串
语法:${variable:offset:length}
例如:
var="hello"
var=${var:3:2}
echo $var //打印出 "lo"
2. 变量长度
例如,找到var变量所包含的长度
${#var}
3. 替换
语法:${variable/pattern/newpattern}
将variable中第一个匹配的pattern替换为newpattern
例如:
var="hello world"
var=${var/l/X}
echo $var # 输出 heXlo world
语法:${variable//pattern/newpattern}
将variable中所有匹配的pattern替换为newpattern
例如:
var="hello world"
var=${var//l/X}
echo $var # 输出 heXXo worXd
第十章 使用sed处理字符串
sed是stream editor的简称。它可以处理字符串(从标准输入或者从指定文件中)的替换,append, insert以及change。
------------------------------------------------------------------------
email : aicrosoft1104@126.com
吃遍天下。