Linux Shell脚本技巧笔记



但是,考虑到Shell脚本的命令限制和效率问题,下列情况一般不使用Shell:
1.资源密集型的任务,尤其在需要考虑效率时(比如,排序,hash等等)。
2.需要处理大任务的数学操作,尤其是浮点运算,精确运算,或者复杂的算术运算(这种情况一般使用C++或FORTRAN 来处理)。
3.有跨平台(操作系统)移植需求(一般使用C 或Java)。
4.复杂的应用,在必须使用结构化编程的时候(需要变量的类型检查,函数原型,等等)。
5.对于影响系统全局性的关键任务应用。
6.对于安全有很高要求的任务,比如你需要一个健壮的系统来防止入侵、破解、恶意破坏等等。
7.项目由连串的依赖的各个部分组成。
8.需要大规模的文件操作。
9.需要多维数组的支持。
10.需要数据结构的支持,比如链表或数等数据结构。
11.需要产生或操作图形化界面 GUI。
12.需要直接操作系统硬件。
13.需要 I/O 或socket 接口。
14.需要使用库或者遗留下来的老代码的接口。
15.私人的、闭源的应用(shell 脚本把代码就放在文本文件中,全世界都能看到)。




脚本编写基础:
#!/bin/sh 开头,放在文件第一行
chmod  +x  filename 给予文件权限
./filename 运行脚本




详细:
以#开头的句子表示注释
shell编程中变量由字符串组成而且不需要进行声明



常用语法和命令:
echo“some text” 将文字内容打印在屏幕上
wc -l/-w/-c file 计算文件行数/单词数/字符数
mv oldname newname mv可以移动文件也可以修改文件名称
grep ‘pattern’ filename 在文件中查找字符串
cut
file filename 得到文件类型



脚本编写:
定义变量:
1.定义变量时,变量名不加美元符号 如:variableNAME=“value”
2.变量名和等号之间不能有空格
3.变量名首个字符必须为字母(a-z,A-Z)
4.变量名中间不能有空格,可以使用下划线(_)
5.变量名中间不能使用标点符号
6.不能使用bash里面的关键字(可用help命令查看保留关键字)


使用变量:在变量名前面加美元符号($)即可


read 变量名 通过read定义的变量,在运行程序是输入(类似C语言的输入变量值),使用方法不变


you_name="wqb"
echo $you_name
echo ${you_name}
变量外的花括号可加可不加,加花括号是为了帮助解释器识别变量边界
注释:推荐给所有变量加上花括号,是一个良好的习惯。


重新定义变量:已经定义的变量,可以被重新定义
wz="www.baidu.com"
echo ${wz}


wz="www.taobao.com"
echo ${wz}
输出结果会把这两个网站都输出.


只读变量:readonly
wz="www.baidu.com"
echo ${wz}
readonly wz //将变量readonly设置成只读,防止后面修改值
wz="www.taobao.com"
echo ${wz}


wz定义为只读后,就无法重复定义,会出现错误.


删除变量:unset
变量删除后不能再次使用,unset无法删除只读变量




变量类型
运行shell时,会同时存在三种变量:
1) 局部变量
局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。


2) 环境变量
所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。


3) shell变量
shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行




变量 含义
$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。
$@ 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。
$? 上个命令的退出状态,或函数的返回值。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。


$echo $$ 查看当前shell的ID(即pid)


命令行参数:运行脚本时传递给脚本的参数称为命令行参数。命令行参数用 $n 表示,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。


例子:
#!/bin/bash
echo "File Name: $0"
echo "First Parameter : $1"
echo "First Parameter : $2"
echo "Quoted Values: $@"
echo "Quoted Values: $*"
echo "Total Number of Parameters : $#"


运行结果
./test.sh Zara Ali
File Name : ./test.sh
First Parameter : Zara
Second Parameter : Ali
Quoted Values: Zara Ali
Quoted Values: Zara Ali
Total Number of Parameters : 2




$* 和 $@ 的区别:


$* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。


但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。


//这个知识点没看懂
#!/bin/bash
echo "\$*=" $*
echo "\"\$*\"=" "$*"
echo "\$@=" $@
echo "\"\$@\"=" "$@"
echo "print each param from \$*"
for var in $*
do
    echo "$var"
done
echo "print each param from \$@"
for var in $@
do
    echo "$var"
done
echo "print each param from \"\$*\""
for var in "$*"
do
    echo "$var"
done
echo "print each param from \"\$@\""
for var in "$@"
do
    echo "$var"
done




执行 ./test.sh "a" "b" "c" "d",看到下面的结果:
$*=  a b c d
"$*"= a b c d
$@=  a b c d
"$@"= a b c d
print each param from $*
a
b
c
d
print each param from $@
a
b
c
d
print each param from "$*"
a b c d
print each param from "$@"
a
b
c
d






$? 可以获取上一个命令的退出状态。所谓退出状态,就是上一个命令执行后的返回结果。退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0,失败回 1。不过,也有一些命令返回其他值,表示不同类型的错误。




转义符:


转义字符 含义
\\ 反斜杠
\a 警报,响铃
\b 退格(删除键)
\f 换页(FF),将当前位置移到下页开头
\n 换行
\r 回车
\t 水平制表符(tab键) 
\v 垂直制表符


若想时这些转义字符(和c语言中的类似)生效必须在echo后加-e 如下:
echo -e "Value of a is $a \n"






命令替换:将输出结果暂时保存,在适当的地方输出


#!/bin/bash
DATE=`date` //将执行date的结果保存在变量DATE中,date左右引号是ESC下面的引号------》重点


echo "Date is $DATE"
USERS=`who | wc -l`
echo "Logged in user are $USERS"
UP=`date ; uptime`
echo "Uptime is $UP"




${var} 变量本来的值
${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
${var:=word} 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。
${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。
若此替换出现在Shell脚本中,那么脚本将停止运行。
${var:+word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。


//例子:脚本直接运行
#!/bin/bash
echo ${var:-"Variable is not set"}
echo "1 - Value of var is ${var}"


echo ${var:="Variable is not set"}
echo "2 - Value of var is ${var}"


unset var
echo ${var:+"This is default value"}
echo "3 - Value of var is $var"


var="Prefix"
echo ${var:+"This is default value"}
echo "4 - Value of var is $var"


echo ${var:?"Print this message"}
echo "5 - Value of var is ${var}"




运算符
#!/bin/bash
val=`expr 2 + 2`
echo "Total value : $val"


注释:
1.达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
2.完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
3.乘号(*)前边必须加反斜杠(\)才能实现乘法运算




关系运算符:关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
运算符 说明 举例
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 true。
-ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否大等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。


举例:
#!/bin/sh
a=10
b=20
if [ $a != $b ]
then
   echo "$a != $b : a is not equal to b"
else
   echo "$a != $b: a is equal to b"
fi






字符运算符:


运算符 说明 举例
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否为0,不为0返回 true。 [ -z $a ] 返回 true。
str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。






#!/bin/sh
a="abc"
b="efg"
if [ $a = $b ]
then
   echo "$a = $b : a is equal to b"
else
   echo "$a = $b: a is not equal to b"
fi






文件测试符(网上有类似的表)






1.sh里没有多行注释,只能每一行加一个#号
2.如果在开发过程中,遇到大段的代码需要临时注释起来,过一会儿又取消注释,怎么办呢?每一行加个#符号太费力了,可以把这一段要注释的代码用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会执行,达到了和注释一样的效果。




单引号
单引号字符串的限制:
1.单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
2.单引号字串中不能出现单引号(对单引号使用转义符后也不行)。


例子:
str='this is a string'


双引号
双引号的优点:
1.双引号里可以有变量
2.双引号里可以出现转义字符


例子:
your_name='qinjx'
str="Hello, I know your are \"$your_name\"! \n"


拼接字符串
your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1


获取字符串长度
string="abcd"
echo ${#string} #输出 4


提取子字符串
string="alibaba is a great company"
echo ${string:1:4} #输出liba


查找子字符串
string="alibaba is a great company"
echo `expr index "$string" is`








数组:
在Shell中,用括号来表示数组,数组元素用“空格”符号分割开
array_name=(value0 value1 value2 value3)
或者
array_name=(
value0
value1
value2
value3
)
或者
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2


读取
valuen=${array_name[2]}


使用@ 或 * 可以获取数组中的所有元素,例如:
${array_name[*]}
${array_name[@]}


获取数组长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}


注释:${!port[@]}返回该数组所有下标






echo:echo是Shell的一个内部指令,用于在屏幕上打印出指定的字符串
echo后面的语句可加双引号也可以省略




显示换行
echo -e "OK!\n" //转义前面要加-e
echo "It is a test"
输出:
OK!
It is a test


显示不换行
echo "OK!\c"
echo "It is a test"
输出:
OK!It si a test


显示结果重定向至文件
echo "It is a test" > myfile


原样输出字符串
若需要原样输出字符串(不进行转义),请使用单引号。例如:
echo '$name\"'


显示命令执行结果
echo `date`




printf::printf 由 POSIX 标准所定义,移植性要比 echo 好。


printf 命令的语法:
printf  format-string  [arguments...]
format-string 为格式控制字符串,arguments 为参数列表。




例子:
# format-string为双引号
$ printf "%d %s\n" 1 "abc"
1 abc
# 单引号与双引号效果一样 
$ printf '%d %s\n' 1 "abc" 
1 abc
# 没有引号也可以输出
$ printf %s abcdef
abcdef
# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
$ printf %s abc def
abcdef
$ printf "%s\n" abc def
abc
def
$ printf "%s %s %s\n" a b c d e f g h i j
a b c
d e f
g h i
j
# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
$ printf "%s and %d \n" 
and 0
# 如果以 %d 的格式来显示字符串,那么会有警告,提示无效的数字,此时默认置为 0
$ printf "The first program always prints'%s,%d\n'" Hello Shell
-bash: printf: Shell: invalid number
The first program always prints 'Hello,0'
$






注意,根据POSIX标准,浮点格式%e、%E、%f、%g与%G是“不需要被支持”。这是因为awk支持浮点预算,且有它自己的printf语句。这样Shell程序中需要将浮点数值进行格式化的打印时,可使用小型的awk程序实现。然而,内建于bash、ksh93和zsh中的printf命令都支持浮点格式






if.....else 语句:
if 语句通过关系运算符判断表达式的真假来决定执行哪个分支。Shell 有三种 if ... else 语句:
if ... fi 语句;
if ... else ... fi 语句;
if ... elif ... else ... fi 语句。
最后必须以 fi 来结尾闭合 if






if ... else 语句的语法:
if [ expression ]
then
   Statement(s) to be executed if expression is true
fi
如果 expression 返回 true,then 后边的语句将会被执行;如果返回 false,不会执行任何语句


if ... else ... fi 语句的语法:
if [ expression ]
then
   Statement(s) to be executed if expression is true
else
   Statement(s) to be executed if expression is not true
fi
如果 expression 返回 true,那么 then 后边的语句将会被执行;否则,执行 else 后边的语句。






if ... elif ... fi 语句可以对多个条件进行判断,语法为:
if [ expression 1 ]
then
   Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
   Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
   Statement(s) to be executed if expression 3 is true
else
   Statement(s) to be executed if no expression is true
fi
哪一个 expression 的值为 true,就执行哪个 expression 后面的语句;如果都为 false,那么执行else语句。


if ... else 语句也可以写成一行,以命令的方式来运行,像这样:
if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;






case ... esac 与其他语言中的 switch ... case 语句类似,是一种多分枝选择结构


ase 值 in
模式1)
    command1
    command2
    command3
    ;;
模式2)
    command1
    command2
    command3
    ;;
*)
    command1
    command2
    command3
    ;;
esac




例子:
echo 'Input a number between 1 to 4'
echo 'Your number is:\c'
read aNum
case $aNum in
    1)  echo 'You select 1'
    ;;
    2)  echo 'You select 2'
    ;;
    3)  echo 'You select 3'
    ;;
    4)  echo 'You select 4'
    ;;
    *)  echo 'You do not select a number between 1 to 4'
    ;;
esac








//没看懂
例子:
#!/bin/bash
option="${1}"
case ${option} in
   -f) FILE="${2}"
      echo "File name is $FILE"
      ;;
   -d) DIR="${2}"
      echo "Dir name is $DIR"
      ;;
   *) 
      echo "`basename ${0}`:usage: [-f file] | [-d directory]"
      exit 1 # Command to come out of the program with status 1
      ;;
esac
运行结果:
$./test.sh
test.sh: usage: [ -f filename ] | [ -d directory ]
$ ./test.sh -f index.htm
$ vi test.sh
$ ./test.sh -f index.htm
File name is index.htm
$ ./test.sh -d unix
Dir name is unix
$




for循环一般格式为:
for 变量 in 列表
do
    command1
    command2
    ...
    commandN
done
列表是一组值(数字、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。
in 列表是可选的,如果不用它,for 循环使用命令行的位置参数。


例如,顺序输出当前列表中的数字:


for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done
运行结果:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5










while:
以下是一个基本的while循环,测试条件是:如果COUNTER小于5,那么返回 true。COUNTER从0开始,每次循环处理时,COUNTER加1。运行上述脚本,返回数字1到5,然后终止。


例子
COUNTER=0
while [ $COUNTER -lt 5 ]
do
    COUNTER='expr $COUNTER+1'
    echo $COUNTER
done








until:
格式
until command
do
   Statement(s) to be executed until command is true
done


例子:
#!/bin/bash
a=0
until [ ! $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值