一、Shell的基础语法
1、循环语句
1)for循环
for 变量 in (list); do
// 编写执行的语句
done
1、遍历1~5
#!/bin/bash
for i in 1 2 3 4 5;do
echo "当前的数字是$i";
done
2、遍历1到100的偶数
第一种写法:
#!/bin/bash
for i in {1..100}; do
if [ $[i % 2] -eq 0 ]; then
echo "偶数是$i"
fi
done
for i in {1..100}; do
if (( (i % 2) == 0 )); then
echo "偶数是$i"
fi
done
for i in {0..100..2}; do
echo "偶数是$i"
done
3、遍历查询出来的结果
#!/bin/bash
for i in `ls /root`; do
echo $i
done
2) while循环
while 条件; do
执行语句
done
// 死循环
while true; do
执行语句
done
1~100之间相加
#!/bin/bash
i=1
sum=0
while [ $i -le 100 ]; do
sum=$[ sum + i]
((i++))
done
echo $sum
// 每隔一秒钟打印一个当前时间
#!/bin/bash
while true; do
date
sleep 1
done
2、分支语句中的switch
语法
case 值 in
匹配的值1)
执行语句
;;
匹配的值2)
执行语句
;;
esac
案例:
在控制台输入数据 1~7,如果是1 打印星期一
#!/bin/bash
echo "请输入1~7之间的数字"
read num
case $num in
1) echo "星期一"
;;
2) echo "星期二"
;;
3) echo "星期三"
;;
4) echo "星期四"
;;
5) echo "星期五"
;;
6) echo "星期六"
;;
7) echo "星期日"
;;
esac
3、跳出循环(break contiune)
break 跳出所有的循环
continue 跳出本次循环
每隔1s打印时间,当打印到第10次的时候,跳出该循环
#!/bin/bash
i=1
while true; do
date
sleep 1
if [ $i -eq 10 ];then
break
fi
((i++))
done
continue 跳出本次循环,进入下一个循环
打印1~100之间不是10的倍数
#!/bin/bash
for i in {1..100}; do
if test $[ i % 10 ] -eq 0; then
continue
fi
echo $i
done
4、函数(类似于java中的方法)
function 方法名()
{
//执行语句
[return xxx;]
}
快速定义个方法,然后执行
#!/bin/bash
function showName()
{
echo "该方法被执行了"
}
showName
如何定义有参数的方法:
function showName2()
{
echo "打印参数1 $1"
echo "参数二是:$2"
}
showName2 1 100 1000
5、数组
bash中,只支持一维数组,不支持多维数据。
数组的名字=(val1 val2 val3 ...)
my_arr=(a b c d "E") 定义数组,并且赋值。
//直接通过下标赋值
my_arr2[0]=hello
my_arr2[1]=world
my_arr2[2]=java
数组的循环:
第一种方式类似于:foreach
#!/bin/bash
my_arr=(AA BB CC)
for str in ${my_arr[*]}
do
echo $str
done
第二种使用下标的方式
#!/bin/bash
my_arr=(AA BB CC)
length=${#my_arr[*]}
for((i=0;i<length;i++));
do
echo ${my_arr[$i]}
done
合并起来的一个脚本是:
#!/bin/bash
echo "使用第一种方式循环:"
my_arr=(AA BB CC)
for str in ${my_arr[*]}
do
echo $str
done
echo "使用第二种方式循环:"
length=${#my_arr[*]}
for((i=0;i<length;i++));
do
echo ${my_arr[$i]}
done
6、脚本文件相互加载
a.sh 中定义了一个数组,b.sh中直接使用
a.sh中直接定义个数组
#!/bin/bash
echo "我是a脚本文件:"
my_arr=(AA BB CC)
b.sh中使用a.sh中的数组(使用之前要加载,类似于java中的导包)
#!/bin/bash
source ./a.sh #加载文件中的内容
for str in ${my_arr[*]}
do
echo $str
done
二、shell脚本的高级部分
grep 、 awk 、sed 号称是shell编程的三剑客
1、cut —提取,从命令结果中提取对应的内容
准备数据 1.txt
111:aaa:bbb:ccc
222:ddd:eee:fff
333:ggg:hhh
444:iii
cut 后面的 -c 的意思是按照字符选取内容
参数 | 英文 | 含义 |
---|---|---|
-d ‘分隔符’ | delimiter | 指定分隔符 |
-f n1,n2 | fields | 分割以后显示第几段内容, 使用 , 分割 |
参数 | 英文 | 含义 |
---|---|---|
-c | characters | 按字符选取内容 |
范围控制
范围 | 含义 |
---|---|
n | 只显示第n项 |
n- | 显示 从第n项 一直到行尾 |
n-m | 显示 从第n项 到 第m项(包括m) |
1、提取1.txt中前两行的第五个字符
head -2 1.txt // 查看文件的前两行
head -2 1.txt | cut -c 5
cut 本身也可以直接提取内容
cut -c 5 1.txt
2、截取1.txt文件中前两行以:进行分割的1,2,3段内容
head -2 1.txt | cut -d ':' -f 1,2,3
head -2 1.txt | cut -d ':' -f 1-3
2、sort 排序
准备数据:2.txt
banana
apple
pear
orange
pear
对字符串进行排序,去重
参数 | 英文 | 含义 |
---|---|---|
-u | unique | 去掉重复的 |
1、去重数据
2、数值类型操作
对数值类型进行的操作
参数 | 英文 | 含义 |
---|---|---|
-n | numeric-sort | 按照数值大小排序 |
-r | reverse | 使次序颠倒 |
准备数据:3.txt
1
3
5
7
11
2
4
6
10
8
9
3)对成绩进行排序
参数 | 英文 | 含义 |
---|---|---|
-t | field-separator | 指定字段分隔符 |
-k | key | 根据那一列排序 |
造数据: 4.txt
zhangsan 68 99 26
lisi 98 66 96
wangwu 38 33 86
zhaoliu 78 44 36
maqi 88 22 66
zhouba 98 44 46
需求:根据第二个成绩进行倒序排序
cat 4.txt | sort -t ' ' -k 3
3、wc (wordcount)
wc 跟上文件名 显示文件的字节数,单词数,文件的行数
造数据:5.txt
111
222 bbb
333 aaa bbb
444 aaa bbb ccc
555 aaa bbb ccc ddd
666 aaa bbb ccc ddd eee
如果只想显示某一些数据:
参数 | 英文 | 含义 |
---|---|---|
-c | bytes | 字节数 |
-w | words | 单词数 |
-l | lines | 行数 |
wc -l 5.txt
wc -l 1.txt 2.txt 3.txt 4.txt 5.txt
wc -l *.txt
我想看一下某个文件夹下有多少个文件
ls /etc | wc -w
ll /etc | wc -l
4、awk(重点)
awk可以实现模糊查询,按需截取字符串,进行判断以及简单的运算
1)查询 搜索名字中含有zhang 和li 的学生成绩
命令 | 含义 |
---|---|
awk ‘/搜索字符/‘ score.txt | 模糊查询 |
模糊查询 ‘张三’ ‘张三三’
cat 4.txt | awk '/zhang|li/'
awk '/zhang|li/' 4.txt
2、指定分隔符,按照下标显示内容
命令 | 含义 |
---|---|
awk -F ‘,’ ‘{print 2, $3}’ 文件 | 操作1.txt文件, 根据 逗号 分割, 打印 第一段 第二段 第三段 内容 |
选项
选项 | 英文 | 含义 |
---|---|---|
-F ‘,’ | field-separator | 使用 指定字符 分割 |
$ + 数字 | 获取第几段内容 | |
$0 | 获取 当前行 内容 | |
NF | field | 表示当前行共有多少个字段 |
$NF | 代表 最后一个字段 | |
$(NF-1) | 代表 倒数第二个字段 | |
NR | 代表 处理的是第几行 |
打印4.txt 中每个学生的姓名以及前两门的成绩
cat 4.txt | awk -F ' ' '{print $1,$2,$3}'
命令 | 含义 |
---|---|
awk -F ‘ ‘ ‘{OFS=”===”}{print 2, $3}’ 1.txt | 操作1.txt文件, 根据 逗号 分割, 打印 第一段 第二段 第三段 内容 |
选项 | 英文 | 含义 |
---|---|---|
OFS=”字符” | output field separator | 向外输出时的段分割字符串 |
awk中使用函数
命令 | 含义 |
---|---|
awk -F ‘,’ ‘{print toupper($2)}’ 1.txt | 操作1.txt文件, 根据 逗号 分割, 打印 第一段 第二段 第三段 内容 |
常用函数如下:
函数名 | 含义 | 作用 |
---|---|---|
toupper() | upper | 字符 转成 大写 |
tolower() | lower | 字符 转成小写 |
length() | length | 返回 字符长度 |
实战:
cat 4.txt | awk -F ' ' '{print toupper($1)}'
awk中还可以添加条件判断
cat 4.txt | awk -F ' ' '{if($4>60) print $1,$4}'
cat 4.txt | awk -F ' ' '{if($4>60) print $1,$4,"及格";else print $1,$4,"不及格"}'
awk中可以进行begin,end语句
命令 | 含义 |
---|---|
awk ‘BEGIN{初始化操作}{每行都执行} END{结束时操作}’ 文件名 | BEGIN{ 这里面放的是执行前的语句 } {这里面放的是处理每一行时要执行的语句} END {这里面放的是处理完所有的行后要执行的语句 } |
//求最后一个成绩的总分
cat 4.txt | awk -F ' ' 'BEGIN{print "开始计算成绩总和"}{total=total+$4}END{print total}'
它是由三部分组成的
BEGIN{} 这一部分只执行一次
END{} 该代码块中的语句也只执行一次
中间{} 每读取一行数据,就执行一次
BEGIN 和 END 可以选择性的使用
// 获取记录条数:
cat 4.txt | awk -F ' ' 'BEGIN{print "开始计算成绩总和"}{total=total+$4}END{print total,NR}'
// 获取平均分
cat 4.txt | awk -F ' ' 'BEGIN{print "开始计算成绩总和"}{total=total+$4}END{print total,NR,(total/NR)}'
5、sed操作 —实现过滤和替换
1、可以进行查询操作
命令 | 含义 |
---|---|
sed 可选项 目标文件 | 对目标文件 进行 过滤查询 或 替换 |
可选参数
可选项 | 英文 | 含义 |
---|---|---|
p | 打印 | |
$ | 代表 最后一行 | |
-n | 仅显示处理后的结果 | |
-e | expression | 根据表达式 进行处理 |
2、搞一些数据 6.txt
aaa java root
bbb hello
ccc rt
ddd root nologin
eee rtt
fff ROOT nologin
ggg rttt
3、列出6.txt中的3~5行的数据
cat 6.txt | sed -n -e '3,5p'
显示第一行到最后1行的数据:
cat 6.txt | sed -n -e '1,$p'
显示行号:
可选项 | 含义 |
---|---|
= | 打印当前行号 |
打印第三行到第五航的数据,显示行号
一种写法,没有使用sed ,而是使用了cat -n
cat -n 6.txt|sed -n -e '3,5p'
另一种写法:
sed -n -e '3,5=' -e '3,5p' 6.txt
sed进行查找:
// 需求是查找每一行中包含login的数据
cat 6.txt | sed -n -e '/login/p'
cat 6.txt| grep login
不区分大小写的查找,使用 I 参数
Sed 中可以使用正则表达式:
cat 6.txt|sed -n -r -e '/r+t/p'
-r 后面可以跟正则表达式 +t t字母出现一次到多次
Sed 进行删除操作:
先学习一个新命令 nl 可以查看文件,该文件自动添加行号
选项使用d 进行删除
显示除了3到5行的所有数据:
nl 6.txt | sed -e '3,5d'
nl 6.txt | sed -e '3,$d' // 只显示前两行数据了
还可以使用sed修改内容
参数 | 英文 | 含义 |
---|---|---|
i | insert | 目标前面 插入内容 |
a | append | 目标后面 追加内容 |
1、在6.txt的第一行前面插入 xxxxxxx,并显示行号
nl 6.txt | sed -e '1i xxxxxxxx'
2、在6.txt的第二行后面插入 SSSSSSS,并显示行号
nl 6.txt | sed -e '2a SSSSSSSS'
sed还可以进行数据的替换
s/oldString/newString/ | replace | 替换 |
---|---|---|
把6.txt中的nologin替换成为huawei,并显示行号
cat 6.txt | sed -e 's/nologin/huawei/' // 按照字符串进行替换
cat 6.txt | sed -e '3c laoyan' // 按照行进行替换
以上的替换都是没有修改原来的数据的,sed也可以直接对原数据进行直接更改。
直接更改数据,首先数据进行备份
cp 6.txt 7.txt
sed -i -e 's/nologin/huawei/' 7.txt
sed -i -e '2c laoyanlaoyan' 7.txt
sed -i -e '1,2d' 7.txt // 真删除数据
Sed综合练习:获取本机的IP地址
ifconfig 在 linux上可以获取本机的IP信息
ipconfig 在windows上可以获取IP地址信息
因为我们使用的是mini版,没有这个服务:
yum search ifconfig
yum install -y net-tools.x86_64
安装完毕就可以使用ifconfig 这个服务了。
符号 | 含义 | |
---|---|---|
^ | 表示开始 | ^aaa 表示以 aaa 开始 |
$ | 表示结尾 | bbb$ 表示以 bbb 结尾 |
.* | 表示任意 | ^.* 表示以 任意字符开始 |
需求是:通过ifconfig 命令获取我的IP地址
ifconfig ens33 | grep 'inet ' | sed -e 's/inet //' | sed -e 's/ netmask.*//'
6、split 文件切割
创造数据:拷贝一个/etc/services
cp /etc/services ~/
mv services big.txt
ll 查看文件的大小
按照字节进行切割:
split -b 100k big.txt
split -l 3000 big.txt
7、tr 替换和删除
tr 被替换的字符 新字符 是translate 的缩写
搞点数据:8.txt
laoyan
HELLO
abc12def34g
替换:
删除操作:
使用tr 进行一个单词计数的练习
9.txt
hello,world,hadoop
hive,sqoop,flume,hello
kitty,tom,jerry,world
hadoop
将单词中的,替换为换行符
cat 9.txt | tr ',' '\n'
//接着使用排序,去重等操作
cat 9.txt | tr ',' '\n' | sort | uniq
// 接着可以进行单词重复记录的数据
cat 9.txt | tr ',' '\n' | sort | uniq -c
8、uniq 去重
uniq 命令用于检查及删除文本文件中重复出现的行,一般与 sort 命令结合使用
造一些数据10.txt
张三 98
李四 100
王五 90
赵六 95
麻七 70
李四 100
王五 90
赵六 95
麻七 70
cat 10.txt | sort | uniq
9、tee 可以将数据输送到各个文件中 ,跟一个水管一样
cat 10.txt | sort | uniq -c | tee a.txt b.txt c.txt