学习 Linux Shell脚本笔记
PS:看完了,跟着测试了主要的,现在晚上时间21:00,花了近一天
因为网站要用到定时删除一定时间以前的文件,所以要用的xshell,无意间看到一位博主推荐的30分钟玩转xshell编程
于是一头扎进去开始学习。
学习链接:http://c.biancheng.net/cpp/view/6999.html
一基础:
echo $PATH #获取环境变量路径
echo $SHELL #获取默认shell默认使用环境变量
创建xx.sh并执行
#在环境路径下建立xx.sh文件内容如下
#!/bin/bash #约定脚本使用的解释器
#范例脚本
echo "what is your name"
read person #这里使用read命令获取stdin命令窗口输入内容获取变量
echo "hello,$person"
#写完后保存
#给予权限
chmod -x xx.sh
#提示:w:读 r:写 x:执行
#完成后执行,切记一定要./开头:
./xx.sh
二:变量
#切记,区别于php,变量赋值左右不能有空格,一定要注意,但是运算必须有空格
#变量声明如下,明明规范等于php,默认Bash shell都会识别为字符串,如果值包含空格等必须使用引号包围
variable=value
variable='value'
variable="value"
#使用如下,{}是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界
#推荐给所有变量加上花括号{ },这是个良好的编程习惯。
author="严长生"
echo $author
echo ${author}
skill="Java"
echo "I am good at ${skill}Script"
#和php一样,变量可以被重新赋值
url="aa"
echo ${url}
url="bb"
echo ${url}
#值的引号使用等于php,单引号不解析变量,且不转义字符,双引号解析变量可以转义字符,所以如果不是原样输出,没有特殊需要最好都用双引号
#变量的赋值有两种,推荐使用第二种,如下
log=`cat test.txt` #使用反引号,用以和单引号混淆
echo $log
log=$(cat test.txt) #使用()号,推荐使用
echo $log
#只读变量
readonly url="aa"
url="bb"
#会报错:url: readonly variable
#删除变量使用unset,等于php
url="aa"
unset url
#变量类型
#运行shell时,会同时存在三种变量:
#1) 局部变量
#局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
#2) 环境变量
#所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
#3) shell变量
#shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
*/
特殊变量,可echo 测试:
$0 | 当前脚本的文件名 |
$n | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。 |
$? | 上个命令的退出状态,或函数的返回值。 |
$$ | 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 |
#!/bin/sh
echo "sh name:$0"
echo "fist param:$1"
echo "two param:$2"
echo "all param:$@"
echo "all param:$*"
echo "param number:$#"
#输入命令,在执行的脚本命令后边传递参数:
./dir.sh A B
#或者后面跟字符串./test.sh "a" "b" "c" "d"
#输出如下:
sh name:./dir.sh
fist param:A
two param:B
all param:A B
all param:A B
param number:2
# $* 和 $@ 的区别,他们不被双引号包含时都是以$1,$2输出所有参数
echo "\$*=" $*
echo "\"\$*\"=" "$*" #在对双引号包含的"$*"进行for循环时,会将参数当一个整体输出(可理解为字符串)
echo "\$@=" $@
echo "\"\$@\"=" "$@"
#举例:
./test.sh "a" "b" "c" "d" #for "$*"时 会将参数作为一个整体全部输出,而不是每个参数
#退出状态
echo $?
#在脚本里执行输出上一个命令执行后的返回结果,大部分命令执行成功会返回 0,失败返回 1
Shell替换:Shell变量替换,命令替换,转义字符:
转义字符 | 含义 |
\\ | 反斜线 |
\a | 警报、响铃 |
\b | 退格(删除键) |
\f | 换页(FF),将当前位置移到下页开头 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符(tab键) |
\v | 垂直制表符 |
#如果输出内容里包含转义字符
a=10
echo -e "value of a is $a \n"
#这里加上-e 表示对转义字符进行替换,表示输出的结尾加上换行
value of a is 10
#如果这里不加上-e的话,则会原样输出:
value of a is 10\n
#可以使用 echo 命令的 -E 选项禁止转义,默认也是不转义的;使用 -n 选项可以禁止插入换行符。
#命令替换
变量替换表,相当于php某些框架中模板中输出变量的用法
形式 | 说明 |
---|---|
${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 的值。 |
shell运算符
#原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
#expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
#注意两点:
#一:表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2
#二:完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
#例如
#!/bin/bash
val=`expr 2 + 2`
echo $val
a=10
b=20
val=`expr $a \* $b`
echo "a * b : $val"
if [ $a != $b ]
then
echo "a is not equal to b"
fi
#乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | `expr $a + $b` 结果为 30。 |
- | 减法 | `expr $a - $b` 结果为 10。 |
* | 乘法 | `expr $a \* $b` 结果为 200。 |
/ | 除法 | `expr $b / $a` 结果为 2。 |
% | 取余 | `expr $b % $a` 结果为 0。 |
= | 赋值 | a=$b 将把变量 b 的值赋给 a。 |
== | 相等。用于比较两个数字,相同则返回 true。 | [ $a == $b ] 返回 false。 |
!= | 不相等。用于比较两个数字,不相同则返回 true。 | [ $a != $b ] 返回 true。 |
关系运算符列表
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
运算符 说明 举例 -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。
a=10
b=20
if [ $a -eq $b ] #注意啊,这里[]两边必须空格,否则报错
then
echo "$a -eq $b : a is equal to b"
else
echo "$a -eq $b: a is not equal to b"
fi
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
#!/bin/sh
a=10
b=20
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a -lt 100 -a $b -gt 15 : returns true"
else
echo "$a -lt 100 -a $b -gt 15 : returns false"
fi
#输出
10 -lt 100 -a 20 -gt 15 : returns true
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等,相等返回 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。 |
详细请看:http://c.biancheng.net/cpp/view/2736.html
Shell字符串
#字符串拼接
a="this is a"
b="fllow,"$a"!"
c="fllow,${a} !"
echo $b $c
#输出内容如下:
fllow,this is a! fllow,this is a !
#获取字符串长度
string='abcd'
echo ${#string}
#输出
4
#提取子字符串
string="alibaba is a great company"
echo ${string:1:4}
#输出liba,也就是第1-第四的字符
Shell数组:shell数组的定义、数组长度
#shell中数组和php有点类似,没有多维数组,定义时用(),值与值之间用空格分开,读取时用下标,下标也是0开始
array=(a b c d)
array=(
a
b
c
d
)
array[0]=a
array[1]=b
array[2]=c
array[3]=d
#读取格式为
${array[0]}
#使用*和@可以获取数组中所有元素
${array[*]}
${array[@]}
#获取数组长度
${#array[*]}
${#array[@]}
@获取数组单个元素的长度
${#array[n]}
Shell if else语句,三种用法
#第一种
if [ $a == $b ]
then
echo "a is equal to b"
fi
#第二种
if [ $a == $b ]
then
echo "a is equal to b"
else
echo "a is not equal to b"
fi
#第三种
a=10
b=20
if [ $a == $b ]
then
echo "a is equal to b"
elif [ $a -gt $b ]
then
echo "a is greater than b"
elif [ $a -lt $b ]
then
echo "a is less than b"
else
echo "None of the condition met"
fi
Shell test命令
# test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
#数值
num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo 'The two numbers are equal!'
else
echo 'The two numbers are not equal!'
fi
#字符串
num1=100
num2=100
if test num1=num2
then
echo 'The two strings are equal!'
else
echo 'The two strings are not equal!'
fi
#文件测试,比较命令请参考文档
cd /bin
if test -e ./notFile -o ./bash
then
echo 'One file exists at least!'
else
echo 'Both dose not exists!'
fi
#与( ! )、或( -o )、非( -a )三个逻辑操作符用于将测试条件连接起来,其优先级为:“!”最高,“-a”次之,“-o”最低。例如:
Shell case esac语句
#直接举例吧
#其间所有命令开始执行直至 ;;。 ;; 与其他语言中的 break 类似
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
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
Shell 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
#顺序输出字符串中的字符
for str in 'This is a string'
do
echo $str
done
#运行结果:
This is a string
#显示主目录下以 .bash 开头的文件:
for FILE in $HOME/.bash*
do
echo $FILE
done
#结果
/root/.bash_history
/root/.bash_logout
/root/.bash_profile
/root/.bashrc
Shell while循环
#例子
count=1
while [ $count -lt 6 ]
do
echo $count
let count++
done
#输出
1
2
3
4
5
6
#读取磁盘信息
echo 'type <CTRL-D> to terminate'
echo -n 'enter your most liked film: '
while read FILM
do
echo "Yeah! great film the $FILM"
done
Shell until循环,和while相反,遇到true时才停止
#和while一样,循环里运算用法要注意
#输出 0 ~ 9 的数字
a=0
until [ ! $a -lt 10 ]
do
echo $a
let ++a
done
break命令
#像大多数编程语言一样,Shell也使用 break 和 continue 来跳出循环。
while :
do
echo -n "input your number between 1 to 5"
read num
case $num in
1|2|3|4|5) echo "your number is $num"
;;
*) echo 'stop'
break
;;
esac
done
#和php一样,满足条件break跳出循环 break n跳出第几层循环
for var1 in 1 2 3
do
for var2 in 0 5
do
if [ $var1 -eq 2 -a $var2 -eq 0 ]
then
break 2
else
echo "$var1 $var2"
fi
done
done
#coutinue表示跳出本次循环 coutinue n跳出第几层循环
while :
do
echo -n "Input a number between 1 to 5: "
read aNum
case $aNum in
1|2|3|4|5) echo "Your number is $aNum!"
;;
*) echo "You do not select a number between 1 to 5!"
continue
echo "Game is over!"
;;
esac
done
Shell函数:Shell函数返回值、删除函数、在终端调用函数
#可以带function 也可以不带,调用时后面不需要()
#实例
number_one () {
echo "Url_1 is http://see.xidian.edu.cn/cpp/shell/"
number_two
}
number_two () {
echo "Url_2 is http://see.xidian.edu.cn/cpp/u/xitong/"
}
number_one
#使用函数接受结果请使用$?
funWithReturn(){
echo "The function is to get the sum of two numbers..."
echo -n "Input first number: "
read aNum
echo -n "Input another number: "
read anotherNum
echo "The two numbers are $aNum and $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
# Capture value returnd by last command
ret=$?
echo "The sum of two numbers is $ret !"
#删除函数
unset .f function_name
#/etc/profile
#可以将函数定义在以上目录,这样每次登录后,在命令提示符后面输入函数名字就可以立即调用
Shell函数参数
#通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...
funWithParam(){
echo "The value of the first parameter is $1 !"
echo "The value of the second parameter is $2 !"
echo "The value of the tenth parameter is $10 !"
echo "The value of the tenth parameter is ${10} !"
echo "The value of the eleventh parameter is ${11} !"
echo "The amount of the parameters is $# !" # 参数个数
echo "The string of the parameters is $* !" # 传递给函数的所有参数
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
#注意:注意,当n>=10时,需要使用${n}来获取参数
#前面讲过特殊变量,$*:参数个数,$*和$@获取所有参数
Shell输入输出重定向:Shell Here Document,/dev/null文件
#Unix 命令默认从标准输入设备(stdin)获取输入,将结果输出到标准输出设备(stdout)显示。一般情况下,标准输入设备就是键盘,标准输出设备就是终端,即显示器。
#命令的输出不仅可以是显示器,还可以很容易的转移向到文件,这被称为输出重定向。
#输出重定向 用>
echo line 1 > users #输出重定向会覆盖文件内容
echo line 2 >> users #使用 >> 追加到文件末尾
#查看
cat users
#输入重定向,可以从文件获取输入 用<
#计算 users 文件中的行数
wc -l users
#输入重定向到 users 文件
wc -l < users
#如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
#如果希望屏蔽 stdout 和 stderr,可以这样写:
command > /dev/null 2>&1
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
Shell文件包含
#包含外部脚本,将外部脚本的内容合并到当前脚本。
#一种
. filename #简单起见,一般使用点号(.),但是注意点号(.)和文件名中间有一空格
#二种
source filename
#注意:被包含脚本不需要有执行权限。
#在相同目录创建url.sh,内容为
a='thi s inlcude strinf'
#在使用test.sh
. ./url.sh
echo $a
#即可