echo 格式化输出
# 输出 hello,并换行
echo "hello"
# 输出 hello,不换行
echo -n "hello"
# 输出 hello,不换行,并对 转义字符进行转义
echo -n -e "\t hello"
read 程序交互
# 输入用户名密码,密码10s内输入完成,最大长度6位
# -p 打印信息, -s 不回显, -t 限制时间,-n 限制长度
echo -n "username: "
read user
echo -n "password: "
read -s -t10 -n6 pwd
echo "username: $user, password: $pwd"
# 简单写法
read -p "username: " user
变量
1、本地变量:用户私有变量,只有本用户可以访问,保存在家目录的 .bash_profile、.bashrc文件中
2、全局变量:所有用户都可以使用,保存在 /etc/profile 文件中
3、用户自定义变量:用户自定义,比如脚本中的变量
定义变量格式: 变量名=值 (=两边不能有空格)
字符串用单引号或者双引号引起来
# 终端中取消变量
unset 变量名
# 特殊变量
$0: 脚本的名字
$*: shell的所有参数
$N: shell的第n个外传参数
$#: 代表参数数量
$_: 最后一个执行的命令
$$: 脚本的进程号
# 示例
#!/bin/bash
echo "脚本的名字是:$0"
echo "脚本的参数是: $*"
echo "脚本的第3个参数是:$3"
echo "脚本的参数数量是:$#"
echo "脚本的进程号是:$$"
echo "脚本的最后一个命令是:$_"
数组
# 基本数组
array=('a' 'b' 'c' 'd')
echo ${array[2]}
echo ${array[@]}
echo ${array[@]:1:2}
# 关联数组
#!/bin/bash
declare -A array1;
declare -A array2;
array1=([name]=aaa [age]=10)
echo ${array1[name]}
array2[name]=bbb
array2[age]=20
echo ${array2[name]}
运算
# 数学比较运算
-eq 等于
-gt 大于
-lt 小于
-ge 大于或等于
-le 小于或等于
-ne 不等于
# 文件比较与检查
-d 检查文件是否存在并且为目录
-e 检查文件是否存在(文件或文件夹)
-f 检查文件是否存在并且为文件
-r 检查文件是否存在并且为可读
-w 检查文件是否存在并且为可写
-x 检查文件是否存在并且为可执行
-s 检查文件是否存在并且不为空
-O 检查文件是否存在并且为当前用户所拥有
-G 检查文件是否存在并且默认组为当前用户组
file1 -nt file2 检查file1是否比file2新
file1 -nt file2 检查file1是否比file2旧
# 字符运算
== 等于
!= 不等于
-z 字符串是否为空
-n 字符串是否不为空
# 逻辑运算符
&& 逻辑与
|| 逻辑或
! 逻辑非
# if判断
if [condition]
then commands
fi
# 示例
#!/bin/bash
read -p "请输入目录:" dir
echo $dir
if [ -d $dir ]
then
echo "目录存在!"
else
echo "目录不存在!"
fi
# 示例
#!/bin/bash
if [ $1 -eq $2 ]
then
echo "$1 == $2"
else
if [ $1 -gt $2 ]
then
echo "$1 > $2"
else
echo "$1 < $2"
fi
fi
# 示例
#!/bin/bash
if [ $1 -gt $2 ]
then
echo "$1 > $2"
elif [ $1 -eq $2 ]
then
echo "$1 == $2"
else
echo "$1 < $2"
fi
# 示例
#!/bin/bash
if ((100%3+1 > 10));
then
echo "yes"
else
echo "no"
fi
# for 循环
# 语法1
for var in val1 val2 val3
do
commands
done
# 语法2
for ((变量初始化; 条件; 变量自增减))
do
commands
done
# 示例
#!/bin/bash
for i in `seq 1 2 5`
do
echo $i
sleep 1
done
for (( i=1; i<10; i++ ))
do
if (($i==5))
then
continue
else
echo $i
sleep 1
fi
done
# 监控主机是否存活脚本
for ((;;))
do
ping -c1 $1 &>/dev/null
if [ $? -eq 0 ]
then
echo "`date +"%F %H:%M:%S"`: $1 is up"
else
echo "`date +"%F %H:%M:%S"`: $1 is down"
fi
sleep 5
done
# 示例 (九九乘法表)
#!/bin/bash
for (( i=1; i<10; i++ ))
do
for (( j=1; j<=$i; j++ ))
do
echo -n -e "$i*$j=$((i*j))\t"
done
echo ""
done
# while 循环
while [ condition ]
do
commands
done
# 示例
read -p "account: " account
while [ $account != 'root' ]
do
read -p "acount: " account
done
# until 循环,和while相反,条件为假时循环,条件为真时停止
# case 分支
case 变量 in
条件1)
代码块
;;
条件2)
代码块
;;
*)
代码块
;;
esac
# 示例
#!/bin/bash
read -p "num:" num
case $num in
1)
echo "1"
;;
2)
echo "2"
;;
*)
echo "else"
;;
esac
函数
# 语法1
函数名 () {
代码块
return n;
}
# 语法2
function 函数名 {
代码块
return n;
}
# 示例
#!/bin/bash
start () {
echo "satrt ..."
}
function stop {
echo "stop ..."
}
start
stop
正则表达式
shell支持正则表达式的常见命令:grep、sed、awk。
# 定位符(同时锚定开头和结尾,做精确匹配。单一锚定开头和结尾,做模糊匹配)
^ 锁定开头,^a以a开头,默认指定一个字符
$ 锁定结尾,a$以a结尾,默认指定一个字符
# 精确匹配:以a开头,以c结尾的字符串
egrep "^ac$" file
# 模糊匹配:以a开头的字符串
egrep "^a" file
# 匹配符(匹配字符串)
. 匹配除回车以外的任意字符
() 字符串分组
[] 定义字符类,匹配括号中的一个字符
[^] 对[]中的字符取反
\ 转义字符
| 或
# 示例:匹配以 a或b 开头,以c结尾的字符串
egrep "^(a|b)c$" file
# 限定符(对前面的字符或者字符串做限定说明)
* 某个字符后面加 * 号表示该字符不出现或者出现多次
? 某个字符后面加 ? 号表示该字符不出现或者出现一次
+ 某个字符后面加 + 号表示该字符出现一次或多次
{n,m} 某个字符后面加 {n,m} 号表示该字符最少出现n次,最多出现m次
{m} 某个字符后面加 {m} 号表示该字符正好出现m次
# POSIX 特殊字符
文件内容操作
sed 是一个行(流)编辑器,非交互式的对文件内容进行增删改查操作
sed [options] '{command}[flag]' filename
options命令选项:
-e 将脚本中指定的命令添加到处理输入时执行的命令中。
-f 将文件中指定的命令添加到处理输入时执行的命令中
-n 抑制自动输出
-i 编辑文件内容
-r 使用扩展的正则表达式
! 取反
command命令:
a 在匹配后面添加
i 在匹配前面添加
p 打印
d 删除
s 查找替换
c 更改
y 转换
flag:
数字 表示新文本替换的模式
g 表示用新文本替换现有文本的全部实例
p 表示打印原始内容
w filename 将替换的结果写入文件
输出流操作
awk 能够集过滤、提取、运算为一体,它的工作方式是读取数据,将每一行数据视为一条记录,每条记录以字段分隔符分成若干字段,然后输出各个字段的值。平行命令还有 gawk、pgawk、dgawk。
awk [options] [BEGIN]{program} [END] [file]
options选项:
-F -fs 指定描绘一行中数据字段的文件分隔符,默认为空格
-f file 指定读取程序的文件名
-v var=value 定义awk程序中使用的变量和默认值
awk程序运行优先级:
1) BEIGIN:在开始处理数据流之前执行,不需要数据源,可选项
2)program:如何处理数据流,需要数据源,必选项
3)END:处理完数据流之后执行,需要数据源,可选项
# awk 对字段(列)的提取
字段提取:提取一个文本中的一列数据并打印输出
$0: 表示整个文本
$1: 表示文本行中的第一个数据字段
$N: 表示文本行中的第N个数据字段
$NF: 表示文本行中的最后一个数据字段
# awk 对字段(行)的提取
字段提取:提取一个文本中的一行数据并打印输出
NR==1: 表示第一行
NR==n: 表示第n行
# 示例(输出 test.sh文件第3行第2列的文本)
awk 'NR==3{print $2}' test.sh
awk 'BEGIN{print 100%3}'
echo "hello world" | awk 'NR=1{print $2}'
示例
# 检测一个服务端口
#!/bin/bash
port_status () {
# 创建临时文件
temp_file=`mktemp port_status.XXX`
#1、判断依赖命令telnet是否存在
[ ! -x /usr/bin/telnet ] && echo "telnet: not found command" && exit 1
#2、测试端口 $1:ip $2:port
( telnet $1 $2 <<EOF
quit
EOF
) &> $temp_file
#3、分析文件中的内容,判断结果
if egrep "\^]" $temp_file &> /dev/null;
then
echo "$1 $2 is open"
else
echo "$1 $2 is close"
fi
# 删除临时文件
rm -f $temp_file
}
# 函数传参
port_status $1 $2
sh port_status.sh 192.168.23.103 22
# nginx在线安装脚本
#!/bin/bash
nginx_pkg="nginx-1.20.2.tar.gz"
nginx_source_doc=`echo $nginx_pkg | cut -d "." -f1-3`
nginx_install_doc="/usr/local/nginx"
# 检测
check () {
# 检测当前用户是否为root
if [ $USER != 'root' ]; then
echo "need to be root so that"
exit 1
fi
# 检查wget命令
if [ ! -x /usr/bin/wget ]; then
echo "not found command /usr/bin/wget"
exit 1
fi
}
# 下载
install_pre () {
# 安装依赖
# if ! yum install gcc-* pcre-devel zlib-devel 1>/dev/null
if ! yum -y install gcc-* pcre-devel zlib-devel; then
echo "ERROR: yum install error"
fi
# 下载源码包
if wget http://nginx.org/download/$nginx_pkg; then
tar -zxvf $nginx_pkg
if [ ! -d $nginx_source_doc ]; then
echo "ERROR: not found $nginx_source_doc"
exit 1
else
echo "$nginx_source_doc 解压成功!"
fi
else
echo "ERROR: wget $nginx_pkg file fail"
exit 1
fi
}
# 安装
install () {
cd $nginx_source_doc
echo "nginx configure ..."
if ./configure --prefix=$nginx_install_doc; then
echo "nginx make ..."
if make; then
echo "nginx make install ..."
if make install; then
echo "nginx install success"
else
echo "ERROR: nginx make install fail"
exit 1
fi
else
echo "ERROR: ngin make fail"
exit 1
fi
else
echo "ERROR: nginx configure fail"
exit 1
fi
}
# 启动
start () {
if $nginx_install_doc/sbin/nginx; then
echo "nginx start success"
else
echo "nginx start fail"
fi
}
check
install_pre
install
start
网友评论