共计 6033 个字符,预计需要花费 16 分钟才能阅读完成。
这几天也是刚学习了 shell 脚本的编写,虽然他不像 Python、Java 那样能够编写很大型的项目 (当然我是这么认为),但是在操控 Linux 系统方面,还是有独特的优势的,当然在学习过程中我们也能更好的了解 Linux。接下来,就开始学习吧。后面会有几个小例子,当然都是别的地方挪过来的,我就是代码的搬运工,嘿嘿。喜欢学习的同志们可以点击 Python 聚焦专栏,查看更多知识。
繁琐的括号总结
基本概念
解释器种类
Bourne Shell(/usr/bin/sh 或 /bin/sh)
Bourne Again Shell(/bin/bash)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
Shell for Root(/sbin/sh)
在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash。
脚本编写
指定使用的解释器类型
#!/bin/bash
运行方式
作为可执行程序
chmod +x ./test.sh # 修改权限
./test.sh # 执行
运行时一定要写成./test.sh,因为直接写 test.sh,linux 会去 PATH 里寻找,而一般只有 /bin,/sbin,/usr/bin,/usr/sbin 等在 PATH 中,所以使用./test.sh 告诉系统,就在本目录下找
作为解释器参数
这种方式可以不用在 sh 文件中写明解释器类型,写了也是没有用的
/bin/sh test.sh
基本语法
变量
定义方式和 python 类似,只不过定义过程中不允许使用空格,默认都是字符串类型
declare 命令定义有类型的变量
-i : 定义整型变量
-a : 定义一个数组
-f : 查看系统中所有定义的函数
-F : 查看系统中所有定义的函数名称
-x : 声明一个环境变量 – 在脚本文件中可以直接使用的变量
取消定义的变量:把命令减号改成加号再执行
使用时只需要使用 $ / ${} 就可以了
只读变量:在变量定义后,再使用 readonly 修饰,再次赋值会报错
删除变量:unset var_name, 不能删除只读变量
变量数据修改
语法
说明
${var_name# 规则}
从变量开头进行匹配,将符合最短的数据删除
${var_name## 规则}
从变量开头进行匹配,将符合最长的数据删除
${var_name% 规则}
从变量末尾进行匹配,将符合最短的数据删除
${var_name%% 规则}
从变量末尾进行匹配,将符合最长的数据删除
${变量名 / 旧字符串 / 新字符串}
变量内容符合旧字符串,就将第一个替换
${变量名 // 旧字符串 / 新字符串}
变量内容符合旧字符串,就全部替换
字符串
Shell 字符串
单引号:不能使用变量
双引号:可以使用变量,并转义 \n 等字符
反引号:用于保存要执行的命令,同:$()【点击例子】
在进行拼接的时候是可以出现以下形式的:
“Hello, “$world””
‘Hello, ‘$world”
expr 命令是从 1 开始索引,而普通的提取都是从零开始索引的
求长度
获取字符串长度:$#var_name
${#str}
expr lenth $str
求字串索引
expr index $str substr_reg
substr 其实索引的是其每个字符,返回最小索引的那个
匹配的字串的长度
expr match $str substr_reg
截取
${str:start}
${str:start:lenth}
${str:(start)}/\${str: -start} start 为负数,表示从尾部开始
expr substr $str $start $length
数组
定义:
array_name=(value0 value1 value2 value3) 使用空格分隔元素
array_name[0]=value0 / array_name[1]=value1 下标可以不连续
读取:
单个读取:${array_name[index]}
全部读取:${array_name[@]}
获取长度:
数组长度:length=${#array_name[@]}/length=${#array_name[*]}
单个元素长度:lengthn=${#array_name[n]}
注释
单行:#
多行:
:<<EOF . . . EOF
使用其他符号替代 EOF, 如:’
函数
定义
function func_name {}
func_name () {}
返回值
return : 一般返回一个整数,用于做判断
echo:用于返回数据
printf
局部变量
local 修饰,不进行修饰那么函数执行后,其他地方也可以使用。
函数库
文件后缀是任意的,一般为 lib
一般不会赋予可执行权限
第一行一般使用 #!/bin/echo 输出警告信息,避免用户执行
获取命令行参数
$num:num 为要获取的参数位置,从 0 开始,分别代表文件名,参数 1,参数 2
$#: 传递到脚本的参数个数
$$: 脚本运行的当前进程 ID 号
$!: 后台运行的最后一个进程的 ID 号
$?: 显示最后命令的退出状态。0 表示没有错误,其他任何值表明有错误。
$-: 显示 Shell 使用的当前选项,与 set 命令功能相同。
$* / $@: 以一个单字符串显示所有向脚本传递的参数。
相同点:都是引用所有参数。
不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 ” * ” 等价于 “1 2 3″(传递了一个参数),而 “@” 等价于 “1” “2” “3”(传递了三个参数)。
中括号的使用 (一般可以使用 test 命令替换)
一个变量是否为 0, [$var -eq 0]
ne: 不等于
lt/gt:小于 / 大于
le/ge:小于等于 / 大于等于
一个文件是否存在,[-e $var], 是否是目录,[-d $var]
两个字符串是否相同,[[$var1 = $var2]]
-a/-o:and/or
-e : exist
-r : 是否可读
-w : 是否可写
-n:判断字符串长度是否非 0
-z:判断字符串长度是否为 0
$ : 判断字符串是否非空
运算符:原生 bash 不支持简单的数学运算,需要使用 awk 和 expr,expr 最常用, 并且只能进行整数运算
表达式和运算符之间要有空格
完整的表达式要被 包含
带有转移的字符需要使用 \ 修饰才能使用
使用 $(()) 中间的运算符不需要转义并且不要求有空格,不能进行相等和不等的判断
echo `expr 2 + 2` # 输出 4
成立返回 1,不成立返回 0
在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 “*” 不需要转义符号 “”
浮点数计算:bc
echo “scale=2;1+1.2” | bc
几个常用命令
read 命令
从标准输入中接收一行,并对修饰的变量赋值
read -p “ 请输入一段文字:” -n 6 -t 5 -s password
-p 输入提示文字
-n 输入字符长度限制 (达到 6 位,自动结束)
-t 输入限时
-s 隐藏输入内容
echo
-e 开启转义,对字符串中的转义字符进行转义操作,不区分单双引号
printf
printf “%s” jim
test:一般用于替换中括号
test $num = $num2
流程控制
if . . . else
if condition
then
command1
elif condition1
then
command2
else
commandN
fi
for . . . in
for var in data
do
command1
done
while
while condition
do
command
done
until:与 while 相反操作,条件为 true 时退出循环
死循环
while:
do
command
done
# 使用 true
while true
do
command
done
# 使用 for
for ((; ;))
case
case value in
value1)
command1
;;
value2)
command2
;;
*)
command2
;;
esac
let 执行一个或多个表达式
sed(Stream Editor) 命令详解,对查找到的数据进行处理【点击例子】
# 语法格式:
sed [option] “pattern command” file_name
# 删除文件第一行
sed -i ‘1d’ file_name
option 选项
n: 只输出匹配的行
e: 需要匹配的条件,可以指定多个 -e “pattern command”
f: 指定 sed 文件,用于封装替换 ”pattern command”
r: 用于支持正则表达式
修改输出内容:sed -n ‘s/love/like/g;p’ sed.txt
i: 修改源文件
pattern
可以使用正则表达式
可以使用变量,只要按照脚本使用变量就可以:双引号,$var_name
匹配 / 需要进行转义
按行匹配的时候,行数在后面如果小于前一个匹配模式,那么久只显示满足前一个条件的行
=:显示行号
command
a : 在匹配到行的下一行添加字符串
i:在匹配到行的上一行添加字符串
r:在匹配到行的下一行添加 file 内容
w:将匹配到的行写入文件
d:删除数据
p:打印数据
g:修改数据时全部匹配,3g 表示从第三个开始全部修改,ig 忽略大小写
=:显示匹配到的行号
反向引用
在使用替换字符的时候,修改内容使用 & 表示使用被替换的条件
# 在匹配到 ^la..jim 的后面加 shuai
# &:全匹配,\1:其使用了正则的分组,所以前面需要使用小括号括起来
sed -i ‘s/^la..jim/&shuai/g’ sed.txt
命令详解
awk 工作模式【点击例子】
# 语法格式:
awk ‘BEGIN{}pattern{commands}END{}’ file_name
适合文本处理和报表生成
命令详解
小例子
<span id=”find_user_all”> 查询所有用户 </span>
for user in `cat /etc/passwd | cut -d “:” -f 1`
do
echo “$user”
done
<span id=”start_nginx”> 启动 nginx</span>
nginx_num_process=$(ps -ef | grep nginx | grep -v grep | wc -l)
if [nginx_num_process -eq 0];then
systemctl start nginx
fi
<span id=”num_add”> 用户输入 num, 求 1 -num 之和 </span>
while true
do
read -p “pls input a positive number: ” num
expr $num + 1 &> /dev/null
if [$? -eq 0];then
if [`expr $num \> 0` -eq 1];then
for((i=1;i<=$num;i++))
do
sum=`expr $sum + $i`
done
echo “1+2+3+….+$num = $sum”
exit
fi
fi
echo “error,input enlegal”
continue
done
<span id=”check_nginx”> 检查 Nginx 是否正常运行,宕机则启动它 </span>
this_pid=$$
while true
do
ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/null
if [$? -eq 0];then
echo “Nginx is running well”
sleep 3
else
systemctl start nginx
echo “Nginx is down,Start it….”
fi
done
<span id=”find_mysql”> 查找 mysql 配置文件中有几段 </span>
FILE_NAME=/root/lesson/5.6/my.cnf
function get_all_segments
{
echo “`sed -n ‘/\[.*\]/p’ $FILE_NAME | sed -e ‘s/\[//g’ -e ‘s/\]//g’`”
}
function count_items_in_segment
{
items=`sed -n ‘/\[‘$1’\]/,/\[.*\]/p’ $FILE_NAME | grep -v “^#” | grep -v “^$” | grep -v “\[.*\]”`
index=0
for item in $items
do
index=`expr $index + 1`
done
echo $index
}
number=0
for segment in `get_all_segments`
do
number=`expr $number + 1`
items_count=`count_items_in_segment $segment`
echo “$number: $segment $items_count”
done
<span id=”del_blank”> 删除配置文件中所有的注释行和空行 </span>
sed -i ‘/[:blank:]*#/^$/d’ config.cnf
<span id=”add_not_ano”> 在非 #注释行前加 *</span>
sed -i ‘s/^[^#]/\*&/g’ config.cnf
<span id=”text_insert_mysql”> 文本格式化数据插入 mysql</span>
user=””
password=””
host=””
mysql_conn=”mysql -u”$user” -p”$password” -h”$host””
IFS=”:” # 内置分隔符变量
cat data.txt | while read id name birth sex
do
$mysql_conn -e “insert into school values(‘$id’,’$name’,’$birth’,’$sex’)”
done
<span id=”script_use_ftp”> 脚本使用 ftp</span>
ftp -inv << EOF
open ftp_ip_addr
user user_name password
put file_name
bye
EOF #必须顶格写
<span id=”awk”>awk 小例子 </span>
小东东
nohub + & 后台启动:nohub 不间断的运行程序,关闭窗口也不会关闭进程,& 用于后台运行
netstat -tnlp | grep port:一般用于查看端口
&& 当左侧的命令返回 0(成功) 才会执行右侧命令
cut -d “:” 制定分隔符
free -m:内存使用情况
df -h: 磁盘使用情况
n >& m:将输出文件 m 和 n 合并
n <& m:将输入文件 m 和 n 合并
<< tag:将开始标记 tag 和结束标记 tag 之间的内容作为输入
grep - E 等同于 egrep,用于扩展支持正则表达式
cat -n file 显示行号输出
/sbin/nologin 不可以登陆的用户
[:blank:] 表示空格
^$ 表示空行
sh - x 可以查看执行过程
根据其他表的结构创建新表
create table new_table like other_table
mysql - B 不显示边框 - E 表示垂直显示 - H 输出 html - X 输出 xml - N 不显示列名
mysqldumps 备份 mysql
d : 只导出表结构
t:只导出数据,不导出建表语句
A:导出所有数据库
B:导出一个或者多个数据库
crontab 定时任务