脚本格式
以 #!/bin/bash 开头
#!/bin/bash
cd ~
touch test.txt
echo "I love you" >> test.txt
基本命令
变量
普通变量(局部变量)
变量名=变量值
echo $变量名
环境变量(全局变量)
export 变量名=变量值
# declare -x 变量名=变量值 与export有相同的效果
通常环境变量被定义保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile中。
查看环境变量
env
撤销变量
unset 变量名
a=192.168.88.100-$a
b=‘192.168.88.100-$b’
c=“192.168.88.100-$c”
① 第一种形式,变量$a可以正常解析
② 第二种形式,单引号中的变量无法正常解析,而是原样输出
③ 第三种形式,双引号中的变量可以正常解析
把命令执行结果赋值给变量
变量名='ls'
变量名 #直接调用
shell中特殊的变量
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n | n表示第n个参数 |
$? | 上个命令的退出状态或函数的返回值 |
判断语句
-lt:小于 -le:小于等于
-eq:等于 -gt:大于
-ge:大于等于 -ne:不等于
流程结构
同意使用 i++、break、coutine
if
基本语法结构
if [判断语句]; then
命令
else
命令
fi
案例:
#!/bin/bash
# 定义变量
read -p "请输入需要判断的进程名(httpd):" process
# 通过命令来查看进程是否存在
pgrep $process &>/dev/null
# 通过命令执行的状态来判断是否存在
if [ $? -eq 0 ];then
echo "进程$process存在"
else
echo "进程$process不存在"
fi
case语句
case语句为多选择语句,功能类似if…elif…else
case var in 定义变量;var代表是变量名
pattern 1) 模式1;用 | 分割多个模式,相当于or
command1 需要执行的语句
;; 两个分号代表命令结束
pattern 2)
command2
;;
pattern 3)
command3
;;
*) default,不满足以上模式,默认执行*)下面的语句
command4
;;
esac esac表示case语句结束
例句:
read -p "请输入要管理服务名称:" service
case $service in
httpd)
read -p "请输入您要进行的操作:" action
case $action in
start|S)
systemctl start httpd
;;
stop|T)
systemctl stop httpd
;;
reload|R)
systemctl restart httpd
;;
esac
;;
firewalld)
read -p "请输入您要进行的操作:" action
case $action in
start|S)
systemctl start firewalld
;;
stop|T)
systemvtl stop firewalld
;;
esac
esac
for循环
列表循环
基本语法:
for variable in {list}
do
command
…
done
案例:
for var in {1..10};do echo $var;done
for var in 1 2 3 4 5;do echo $var;done
for var in `seq 10`;do echo $var;done
for var in $(seq 10);do echo $var;done
for var in {10..1};do echo $var;done
for (( i=1;i<=5;i++ ))
do
echo $i
done
不带列表循环
for variable
do
command
…
done
案例:
#!/bin/bash
for var
do
echo $var
done
echo "脚本后面有$#个参数"
shell函数
函数定义
函数名()
{
函数体(一堆命令的集合,来实现某个功能)
}
调用 函数名
function 函数名()
{
函数体(一堆命令的集合,来实现某个功能)
}
shell三剑客
以行为单位,一行一行的处理
正则表达式
大小写的功能恰恰相反
符号 | 功能 |
---|---|
[] | 匹配[ ]中列举的字符 |
. | 匹配任意1个字符 |
\d | 匹配数字,即0-9 |
\s | 匹配空白 |
\W | 匹配特殊字符,即非字母、非数字 |
* | 匹配前一个字符出现0或多次 |
+ | 匹配前一个字符出现1或多次 |
{m} | 匹配前一个字符出现m次 |
{m,n} | 匹配前一个字符出现从m到n次 |
^ | 表示开头 |
$ | 表示结尾 |
(符号) | 分组 |
例子:
[root@node1 ~]# echo 34785y31984 | grep -P ‘\d{4}’ # -P:代表使用正则模式
3478
5y3198
4[root@node1 ~]# echo 123abc4554 | grep -P ‘(\d)(\d)\2\1’
123abc
4554
grep:检索关键词
参数 | 描述 |
---|---|
-P | 模式是Perl正则表达式 |
-i | 忽略大小写 |
-n | 打印行号 |
-o | 只打印匹配的内容 |
-w | 模式匹配整个单词 |
-v | 打印不匹配的行(取反) |
参数很多,其他的可以man命令查看
准备数据集
# vim demo.txt
Hello, this is an example file.
It contains some lines of text.
Let’s use grep to search for specific patterns.
例子:
传统匹配
[root@node1 ~] grep “example” demo.txtHello, this is an
example
file.[root@node1 ~] grep -i “hello” demo.txt
Hello
, this is an example file.正则匹配
[root@node1 ~] grep -P ‘^I’ demo2.txt -i -n
2:I
am a teacher
3:I
am a student
5:I
study python
6:I
study linux.[root@node1 ~] grep -P ‘^.*?t’ demo2.txt
# vim t
est.txt
I am a t
eacher
I am a st
udent
I st
udy python
I st
udy linux.
贪婪匹配:当一行有多个字符符合条件,以最后一个字符为查找值,如果在条件后加一个?就以第一个出现为查找值
sed:实现文件增删改查
概括流程:sed软件从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行
参数 | 说明 |
---|---|
-n | 取消默认的sed软件的输出,常与sed命令的p连用 |
-i | 直接修改文件内容,而不是输出到终端,如果不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件 |
a | 追加,在指定行后添加一行或多行文本 |
c | 取代指定的行 |
d | 删除指定的行 |
i | 插入,在指定行前添加一行或多行文本 |
s | 取代,s#old#new#g==>这里g是s命令的替代标志,注意和g命令区分 |
追加操作:a的全拼是apend,意思是追加
增
sed ‘2a 106,Smith,CSO’ person.txt # 2表示行号,a表示追加
删除操作:d的全拼是delete,意思是删除
范围 | 含义 |
---|---|
10 | 对第10操作 |
10,20 | 对10到20操作,包括10行和20行 |
1~2 | 对1,3,5,7…行操作,start~step |
10,$ | 对10到最后一行($代表最后一行)操作,包括第10行 |
/Tom/ | 对匹配Tom的行操作 |
例子:
sed ‘2d’ person.txt # 删除第二行
sed ‘/Tom/,/Alex/d’ person.txt # 删除包含“Tom”的行到包含“Alex”的行
sed ‘3,$d’ person.txt # 删除3到最后一行
修改操作:c的全拼是change,意思是替换
这里用到的sed命令是:”c”
sed ‘2c 106,Smith,CSO’ person.txt
文本替换格式:
sed -i ‘s/要替换的内容/替换后内容/g’ 文件内容
sed -i ‘s#要替换的内容#替换后内容#g’ 文件内容
sed ‘s#Tom#Eric#g’ person.txt # 将整个文件中的Tome替换成Eric
sed ‘3s#0#9#’ person.txt # 只把第三行的0替换成9
查询操作:p的全拼是print,意思是打印。
sed -n ‘2,3p’ person.txt # -n代表取消默认输出,只输出匹配的文本
sed -n ‘/CTO/p’ person.txt # 打印含CTO的行
awk:实现较复杂的数据分析工作
使用格式:awk potions ‘pattern{action}’ file
pattern:对谁操作,也就是条件。action:怎样操作
awk -F “:” ‘NR>=2 && NR<=6{print NR,$1}’ /etc/passwd
以:作为分隔符,找2~6行,且打印出行号和第一列的数据
名称 | 含义 |
---|---|
NR | 表示行 |
$n | 1,2…表示列数,0表示所有 |
RS | 将一行数据以某一分隔符分成多行,分行符 |
FS | 表示列,等同于上面的-F。分列符 |
$NF | 表示最后一列 |
ORS | 输出分行符 |
OFS | 输出分列符 |
awk ‘BEGIN{RS=“/”}{print NR,$0}’ /server/files/awkfile.txt
BEGIN表示在action在运行命令前的操作
在每行的开始先打印输出NR(记录号行号),并打印出每一行$0(整行)的内容。
我们设置RS(记录分隔符)的值为“/”,表示一行(记录)以“/”结束,后面另起一行
训练
按单词出现频率降序排序
root x root root bin bash
bin x bin bin sbin nologin
daemon x daemon sbin sbin nologin
adm x adm var adm sbin nologin
lp x lp var spool lpd sbin nologin
sync x sync sbin bin sync
shutdown x shutdown sbin sbin shutdown
halt x halt sbin sbin halt
mail x mail var spool mail sbin nologin
uucp x uucp var spool uucp sbin nologin
查询结果:
[root@node1 ~]# awk ‘BEGIN{RS=“[ ]+”}{print $0}’ count.txt |sort |uniq -c |sort -n
1 bash
1 lpd
2 daemon
2 lp
3 adm
3 halt
3 mail
3 root
3 shutdown
3 spool
3 sync
3 uucp
4 var
5 bin
6 nologin
10 x
12 sbinRS=“[ ]+” :以一个或多个空格作为分行符。sort:排序。uniq -c:去重
awk
awk进阶
使用正则表达式作为模式
# 获取以root开头的所有行
awk -F ":" '/^root/' awkfile.txt
#第5列包含shutdown这个字符串,则显示这一行。
awk -F ":" '$5~/shutdown/' awkfile.txt
$5表示第五个区域(列)
~表示匹配(正则表达式匹配)