在浏览器按Ctrl+F查找所需内容。
***.sh文件都用bash命令运行,sh命令有些不兼容。
一、Shell基础-变量
#!/bin/bash
echo "Hello World!"
#赋值
name="liu"
echo ${name}
for skill in Ada Java Coffe; do
echo "I am ${skill}"
done
for fileName in $(ls /mydata); do
echo "${fileName}"
done
# 赋值并修改值
age=12
echo $age
age=24
echo $age
# 只读变量,不能被修改,修改会报错
myCat="Tom"
readonly myCat
myCat="Jorry"
# 删除变量
myPhone="Redmi Note 7 pro"
unset myPhone
echo $myPhone
# 字符串,这里只说双引号
# 字符串长度
str="abcd"
echo ${#str}
# 提取子串
string="myPhone switch Redmi K40"
echo ${string:15:25}
# 查找子字符串,查找i和o的位置,谁先出现就计算谁
string="I am best, I am beautiful"
echo `expr index "${string}" io`
# 数组:支持一维数组,不支持多维数组
# 定义数组,下标范围是没有限制的
array0=(2 3 6 3 6 90)
array1[0]="two"
array1[1]="three"
array1[2]="six"
array1[10]="nine"
# 读取数组
echo ${array0[0]}
echo ${array1[10]}
echo ${array0[@]}
# 获取数组长度
# 数组元素个数
length0=${#array0[@]}
length1=${#array0[*]}
length2=${#array1[1]}
length3=${#array1[@]}
echo "${length0}+${length1}+${length2}+${length3}"
# 多行注释,EOF也可以用其他符号代替,如:!
:<<EOF
echo "sport"
echo "my"
EOF
二、Shell传递参数
#!/bin/bash
# 参数传递:
# 脚本内获取参数的格式为:$n。n 代表一个数字,
# 1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推
echo "文件名:$0"
echo "第一个参数:$1"
echo "第二个参数:$2"
:<<EOF
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。
如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。
如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
EOF
echo "--------------"
echo "第一个参数:$1"
echo "参数个数:$#"
echo "传递的参数以字符显示:$*"
# $*,$@两者的区别
echo "--------------"
echo "-- \$* 演示:结果是一个参数 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示:结果是多个参数--"
for i in "$@"; do
echo $i
done
三、Shell数组
#!/bin/bash
# 数组:只支持一维数组,不支持多维,无需定义大小,下标从0开始,元素之间用空格分隔开
# 定义
array=(A B "C" D)
array[4]=E
array[5]="F"
#读
echo "${array[1]}"
echo "${array[2]}"
echo "${array[4]}"
echo "${array[5]}"
#获取所有元素:*或@
echo "${array[*]}"
echo "${array[@]}"
# 数组长度
echo "${#array[@]}"
四、运算符
#!/bin/bash
val=`expr 2 + 5`
echo "两数之和为:$val"
# 注意:1、表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2
# 2、完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
# 算数运算符:+ - * / % = == !=
# 例:
a=10
b=20
val=`expr $a - $b`
echo "${val}"
val=`expr $a \* $b`
echo "${val}"
if [ $a == $b ]
then
echo "a=b"
fi
if [ $a != $b ]
then
echo "a!=b"
fi
# 注意:1、乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
# 2、if...then...fi 是条件语句,后续将会讲解。
# 3、在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 "*" 不需要转义符号 "\" 。
# 关系运算符:关系运算符只支持数字,不支持字符串,除非字符串的值是数字
# 符号:-eq:= -ne:!= -gt:> -lt:< -ge:>= -le:<=
x=20
y=10
if [ $x -eq $y ]
then
echo "x=y"
else
echo "x!=y"
fi
# 布尔运算符
# 符号:!:非 -o:或 -a:与
if [ $x -ne $y -a $x -gt $y ]
then
echo "x大于y"
else
echo "x+y!=2x"
fi
# 逻辑运算符
# 符号:&&:逻辑与 ||:逻辑或
if [ $a -gt $b || $a -eq $b ]
then
echo "a>=b"
else
echo "a<=b"
fi
# 字符串运算符
# 符号:= != -z:长度是否为0(为0反true) -n:长度是否不为0(不为0true) $:是否为空(不为空反true)
str="abd"
string="qwert"
if [ $str = $string ]
then
echo "相等"
else
echo "不等"
fi
if [ -z "$string" ]
then
echo "字符串长度为0"
else
echo "字符串长度不为0"
fi
if [ $str ]
then
echo "字符串不为空"
else
echo "字符串为空"
fi
:<<EOF
# 注意:
1、-n $a:$a这里应该加上双引号
a=""
if [ -n "$a" ]
then
echo "true"
else
echo "false"
fi
2、条件判断这里用if [[ ... ]],能够防止脚本中的许多逻辑错误。
比如,&&、||、< 和 > 操作符能够正常存在于 [[ ]] 条件判断结构中,
但是如果出现在 [ ] 结构中的话,会报错。
3、
EQ 就是 EQUAL等于
NE 就是 NOT EQUAL不等于
GT 就是 GREATER THAN大于
LT 就是 LESS THAN小于
GE 就是 GREATER THAN OR EQUAL 大于等于
LE 就是 LESS THAN OR EQUAL 小于等于
EOF
# 文件测试运算符
:<<EOF
-b file 检测文件是否是块设备文件,如果是,则返回 true。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。
-d file 检测文件是否是目录,如果是,则返回 true。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。
-p file 检测文件是否是有名管道,如果是,则返回 true。
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true.
-r file 检测文件是否可读,如果是,则返回 true。
-w file 检测文件是否可写,如果是,则返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true.
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。
EOF
file="/mydata/shellTest/Shell-数组.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
五、echo命令
#!/bin/bash
# 显示普通字符
echo "I hava a Tom"
echo I hava a Tom
# 显示转义字符
echo "\"I hava a Jarry\""
echo \"I hava a Jarry\"
# 显示变量
#read:read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
read name
echo "$name is a man"
# 开启转义:-e
echo -e "OK! \n"
echo "I am fine!"
# 显示不换行
echo -e "Are you OK! \c"
echo "OK!"
# 显示结果定向至文件
echo "OK!" > test.txt
# 原样输出字符串
echo '$name\"l'
# 显示命令执行结果
echo `date`
六、printf命令
#!/bin/bash
# printf与C语言里的printf()类似
# 实例
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
:<<EOF
%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,
%c 输出一个字符,%f 输出实数,以小数形式输出。
%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),
任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中 .2 指保留2位小数。
\a 警告字符,通常为ASCII的BEL字符
\b 后退
\c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),
而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f 换页(formfeed)
\n 换行
\r 回车(Carriage return)
\t 水平制表符
\v 垂直制表符
\\ 一个字面上的反斜杠字符
\ddd 表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd 表示1到3位的八进制值字符
EOF
七、test命令
#!/bin/bash
# test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
# 个人感觉用起来比if [ ... ]简单
a=10
b=20
if test $a -eq $b;then
echo "相等"
else
echo "不等"
fi
# 注意:
# 如果 then 另起一行的话 then 前不需要加 ; 否则需要在 then 前加 ;
八、流程控制
#!/bin/bash
# 流程控制
# if ... else ...
a=10
b=10
if [ $a -eq $b ];then
echo "a==b"
else
echo "a!=b"
fi
# 结尾的fi是if倒过来
# if ...
if [ $(ps -ef | grep -c ssh) -eq 3 ];then
echo "ssh相关有三个在运行"
fi
# if ... else-if ... else
x=10
y=2
if [ $x -eq $y ];then
echo "x==y"
elif [ $x -gt $y ];then
echo "x>y"
elif [ $x -lt $y ];then
echo "x<y"
else
echo "x和y无关系"
fi
# 注意:if else 语句经常与 test 命令结合使用
# for循环
# 实例
# 输出数字
for loop in 1 2 3 4 5 6;do
echo "sum$loop : $loop"
done
# 输出字符串
for str in I have a Tom;do
echo $str
done
# while语句
int=1
while(($int<=5));do
echo $int
let "int++"
done
# 实例使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量
# 上面实例的写法需要用bash 去运行,用sh会报错,它不支持这种 C 语言格式的循环写法
# while循环读取键盘信息
echo "按下 <CTRL-D> 退出"
echo -n "输入你最喜欢的网站名: "
while read file
do
echo "$file 是个好网站"
done
# echo -n:-n是不换行的意思
# 无限循环
:<<EOF
while :
do
...
done
或
while true
do
...
done
或
for ((;;))
EOF
# until循环
:<<EOF
until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。
我并不理解上面这说的啥,但必须粘上
EOF
# 实例
a=0
until [ ! $a -lt 10 ];do
echo $a
a=`expr $a + 1`
done
# case ... esac多选择语句
:<<EOF
case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,
是一种多分枝选择结构,每个 case 分支用右圆括号开始,
用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,
esac(就是 case 反过来)作为结束标记。
可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
case 工作方式如上所示,取值后面必须为单词 in,每一模式必须以右括号结束。
取值可以为变量或常数,匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。
取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。
如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
EOF
echo -n "请输入1-2:"
read num
case $num in
1) echo "你选择的是1"
;;
2) echo "你选择的是2"
;;
*) echo "没有选择"
;;
esac
site="one"
case "$site" in
"one") echo "one"
;;
"two") echo "two"
;;
esac
# 跳出循环:break和continue
:<<EOF
break命令允许跳出所有循环(终止执行后面的所有循环)。
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
EOF
九、函数
#!/bin/bash
:<<EOF
格式
[ function ] funname [()]
{
action;
[return int;]
}
说明
1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255
EOF
# 实例
demoFun(){
echo "有史以来我定义的第一个Shell函数!"
}
echo "来吧,展示"
demoFun
echo "结束"
# 实例:带return
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
# 注意:函数返回值在调用该函数后通过 $? 来获得。
# 先定义才能使用,与C一样
# 实例:带参数
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
# 注意:$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
:<<EOF
处理参数的特殊字符
$# 传递到脚本或函数的参数个数
$* 以一个单字符串显示所有向脚本传递的参数
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
EOF
十、输入、输出重定向
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 之间的内容作为输入。
/dev/null文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
$ command > /dev/null 2>&1
**注意:**0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。
例子:清空日志:cat /dev/null > test.log
十一、文件包含
引用其他文件:
语法格式:
. filename # 注意点号(.)和文件名中间有一空格 或 source filename
实例:
test1.sh
#!/bin/bash url="www.liu.com"
test2.sh
#!/bin/bash source ./test1.sh echo "网址:$url"
给予test2.sh可执行权限:chmod 744 test2.sh
运行:bash test2.sh
结果:网址:www.liu.com
**注:**被包含的文件 test1.sh 不需要可执行权限。