mini-shell
- 不适合在root权限下练习shell脚本书写
- 在mac环境下变量赋值不能加空格
- 执行脚本 sh "sh脚本地址"
- 1、${变量#匹配规则} # 从头开始匹配,最短删除
- 2、${变量##匹配规则} # 从头开始匹配,最长删除
- 3、${变量%匹配规则} # 从尾开始匹配,最短删除
- 4、${变量%%匹配规则} # 从尾开始匹配,最长删除
- 5、${变量/旧字符串/新字符串} # 替换变量内的旧字符串为新字符串,只替换第一个
- 6、${变量//旧字符串/新字符串} # 替换变量内的旧字符串为新字符串,全部替换
variable_1="I love you,Do you love me"
echo $variable_1
var1=${variable_1#*ov}
echo ${var1}
var2=${variable_1##*ov}
echo $var2
var3=${variable_1%ov*}
echo $var3
var4=${variable_1%%ov*}
echo $var4
echo $PATH
var5=${PATH/bin/BIN}
echo $var5
var6=${PATH//bin/BIN}
echo $var6
- ${#string}
- expr match $string substr
### 获取字符串长度
# var1="quickstart is a app"
# echo $var1
# ind=`expr index "$var1" start`
# echo $ind
# ind=`expr index "$var1" uniq`
# echo $ind => 1 q<=>q
# ind=`expr index "$var1" cnk`
# echo $ind => 4 c<=>c
### 获取子串长度
# expr match "$string" substr
# 例子:
# var1="quickstart is a app"
# sub_len=`expr match "$var1" app`
### 抽取字符串中的子串
1,${string:position}/${string:position:length}/${string:(-)position}
var1="kafka hadoop yarn mapreduce"
substr1=${var1:10}
substr2=${var1:10:5}
echo $substr1 # op yarn mapreduce
substr3=${var1:-5} # educe
substr4=${var1:-5:2} # ed
# 2,expr substr $string $position $length
# substr5=`expr substr "$var1" 10 5` # oop y
### !注意 使用expr,索引计数是从1开始计算:使用${string:position}是从0开始计算
- 1,
command
- 2,${command}
#1, 获取系统的所有用户并输出
cat /etc/passwd
man cat #获取cat命令及对应功能
# -b为非空输出行编号,从1开始。
# -e显示非打印字符(请参阅-v选项),并显示每一行末尾都有一个美元符号(' $')。
# -n表示输出行数,从1开始。
# -s压缩多个相邻空行,导致输出为单一的间隔。
# -t显示非打印字符(请参阅-v选项),并显示制表符为' ^I'。禁用输出缓冲。
# -v显示非打印字符,使其可见。控制字符打印为' ^X'为control-X;删除字符(八进制0177)打印为' ^?'。非ascii字符(高位集)被打印为“M-”(用于meta),后跟字符对于低7位。
# -d 以“:”分割
# 获取系统的所有用户并输出
cat /etc/passwd | cut -d ":" -f 1
# 格式1
name()
{
command1,
command2,
...
};
# 格式2
function name
{
command1,
command2,
...
}
# 函数调用 直接使用函数名 [function.sh]
function_name $1 $2 => $1 $2为参数
sh function_test.sh 20 + 30 => 50
# 返回值的方式
return
只能返回1-255的整数
通常只是用来供其他地方调用获取状态,因此通常仅返回0或1;0成功1失败;
echo
可以返回任何字符串结果
通常用于返回数据,比如一个字符串值或列表
# 查看执行过程 sh -x aaa.sh
# 不做特殊声明,shell中变量都是全局变量
# Tips:大型脚本程序中函数慎用全局变量
## 局部变量
定义变量时,使用local关键字
函数内和函数外若存在同名变量,则内部变量覆盖外部变量
存在的意义:经常使用的重复代码封装成函数文件
一般不直接执行,而是有其他脚本调用
库文件名的后缀是任意的,但一般使用.lib
库文件通常没有可执行选项
库文件无需和脚本在同级目录,只需在脚本中引用时指定
# 语法格式 find[路径][选项][操作]
-name 查找/etc目录下以conf结尾的文件 find /usr/local/etc/nginx -name '*.conf'
-iname 查找当前目录下文件名为aa的文件,不区分大小写 find . -iname aa
-user 查找文件属于为hdfs的所有文件 find . -user hdfs
-group 查找文件属组为yarn的所有文件 find . -group yarn
-type
f 文件 find . -type f
d 目录 find . -type d
c 字符设备文件 find . -type c
b 块设备文件 find . -type b
l 链接文件 find . -type l
p 管道文件 find . -type p
-size
-n 大小大于n的文件
+n 大小小于n的文件
n 大小等于n的文件
例子1: 查找/etc目录下小于10000字节的文件 find /etc size -1000c
例子2:查找/etc目录大于1M的文件 find /etc size +1M
-mtime
-n n天以内修改的文件
+n n天以外修改的文件
n 正好n天修改的文件
例子1:查找/etc目录下 5天以内修改且以conf结尾的文件 find /usr/local/etc/nginx -mtime -5 -name '*.conf'
例子2:查找/etc目录下 10天之前修改且属主为root的文件 find /usr/local/etc/nginx -mtime +10 -user root
-mmin
-n n分钟以内修改的文件
+n n分钟以外修改的文件
例子1:查找/etc目录下 30分钟之前修改 的文件 find /usr/local/etc/nginx -mmin +30
例子2:查找/etc目录下 30分钟之内修改 的文件 find /usr/local/etc/nginx -mmin -30 -type d
-mindepth n 表示从n级子目录开始搜索
例子:在/etc下的3级子目录开始搜索 find /usr/local/etc/nginx -mindepth 3
-maxdepth n 表示最多搜索到n-1级子目录
例子1:在/etc下搜索符合条件的文件,但最多搜索到2级子目录 find /usr/local/etc/nginx -maxdepth 3 -name '*.conf'
例子2: find /usr/local/etc/nginx -type f -name '*.conf' -size +10k -maxdepth 2
- 命令可以串起来
find /usr/local/etc/nginx -mtime -5 -name '*.conf'
-nouser 查找没有属主的用户
例子 find . -type f -nouser
-nogroup 查找没有数组的用户
例子 find . -type f -nogroup
-perm 查看权限
find . -perm 664
-prune
通常和 -path 一起使用,用于将特定目录排除在搜索条件之外
例子1,查找当前目录下所有普通文件,但排除etc目录
find . -path ./etc -prune -o -type f
例子2,查找当前目录下所有普通文件,但排除etc和opt目录
find . -path ./etc -prune -o -path ./opt -prune -o -type f
例子3,查找当前目录下所有普通文件,但排除etc和opt目录,但属主为hdfs
find . -path ./etc -prune -o -path ./opt -prune -o -type f -a -user hdfs
例子4,查找当前目录下所有普通文件,但排除etc和opt目录,但属主为hdfs,且文件大小必须大于500字节
find . -path ./etc -prune -o -path ./opt -prune -o -type f -a -user hdfs -a -size +500c
-newer file1
查找比file1更新的文件
## 操作
-print 打印输出 一般命令,输出自带
-exec 对搜索到的文件执行特定的操作,格式为-exec 'command' {} \;
例子1,搜索/etc下的文件(非目录),文件名以conf结尾,且大于10k,然后将其删除
find ./etc/ -type f -name '*.conf' -size +10k -exec rm -f {} \;
例子2,将/var/log/目录下以log结尾的文件,且更改时间在7天以上的删除
find /var/log/ -name '*.log' -mtime +7 -exec rm -rf {} \;
例子3,搜索条件和例子1一样,只是不删除,而是将其复制到/root/conf目录下
find ./etc/ -size +10k -type f -name '*.conf' -exec cp {} /root/conf/ \;
-ok 和exec功能一样,只是每次操作都会给用户提示
# 文件查找命令,所属软件包mlocate
# 不同于find命令是在整块磁盘中搜索,locate命令在数据库文件中查找
# find是默认全部匹配,locate则是默认部分匹配
-- updatedb 命令
# 用户更新/var/lib/mlocate/mlocate.db
# 所使用配置文件/etc/updatedb.conf
# 改命令在后台cron计划任务重定期执行
# 查找数据库数据文件相关命令 locate
# locate my.cnf
-- whereis
# -b 只返回二进制文件
# -m 只返回帮助文档文件
# -s 只返回源代码文件
-- which
# -b 只返回二进制文件
## grep
grep server nginx.conf # 从nginx.conf文件中筛选出有server的字符
grep server -v nginx.conf # 从nginx.conf文件中筛选出不是server的字符
grep server -vi nginx.conf # v,i命令同时使用
grep -E "python|PYTHON" nginx.conf
grep -F "py.*" nginx.conf #F 查找字面意思
grep -r love # 文件夹下忽略大小写全部搜索
mkdir test1/test2/test3 -pv
# 了解
-c 只输出匹配行的数量,不显示具体内容
-w 匹配整词
-x 匹配整行
-l 只列出匹配的文件名,不显示具体匹配行内容
## grep 和 egrep的区别
https://blog.51cto.com/mcmvp/1180951
./grep_egrep_fgrep.md
# sed(Stream Editor),流编辑器。对标准或文件逐行处理
# sed的选项
sed 'p' sed.txt 文件数据每一行打印两边
sed -n 'p' sed.txt 文件数据只打印一行
sed -n '/python/p' sed.txt 只打印小写pthon
sed -n -e '/python/p' -e '/PYTHON/p' sed.txt 执行两个匹配表达式
sed -n -f edit.sed sed.txt
sed -n -r '/python|PYTHON/p' sed.txt
sed -n 's/love/like/g;p' sed.txt
sed -n -i -r 's/love/like/g;p' sed.txt # 表达式前面加上-r
# sed中的pattern
1、LineNumber -- 直接指定行号
sed -n "17p" /etc/passwd 打印file文件的第17行
2、StartLine,EndLine -- 指定起始行号和结束行号
sed -n "10,20p" /etc/passwd 打印file文件的10到20行
3、StartLine,+N -- 指定起始行号,然后后面N行
sed -n "10,+5p" /etc/passwd 打印file文件中从第10行开始,往后加5行的所有
4、/pattern1/ -- 正则表达式匹配的行
sed -n "/^root/p" /etc/passwd 打印file文件中以root开头的行
5、/pattern1/,/pattern2/ -- 从匹配到pattern1的行,到匹配到pattern2
sed -n "/^ftp/,/^mail/p" /etc/passwd 打印file文件中第一个匹配到ftp开头的行
6、LineNumber,/pattern1/ -- 从指定行号开始匹配,知道匹配到pattern1的
sed -n "4,/^hdfs/p" file -- 打印file文件中第4行开始匹配,知道匹配到最后也要打印
7、/pattern1/,LineNumber -- 从pattern匹配的行开始,知道匹配到指定行
sed -n "/root/,10p" file -- 打印file文件中匹配root的行,直到第10行结束
# sed中的编辑命令
cp /etc/passwd ./ -- 把/etc/passwd的文件复制到当前文件夹
sed -i '1d' passwd -- 删除文件passwd的第一行
sed -i '1,3d' passwd -- 删除文件passwd的第一行到第三行
sed -i '/\/sbin\/nologin/d' passwd -- 删除文件passwd匹配到的 /sbin/nologin 所在行
sed -i '/^mail/','/^ftp/d' passwd
sed -i '/\/bin\/bash/a canLogin' passwd -- 符合条件行后添加“canLogin”
sed -i '/^hdfs/,/^yarn/i AAA' passwd -- 符合条件行前添加“AAA”
sed -i '/root/r list' passwd -- 符合条件行后添加 list文件中的内容
sed -n '/\/bin\/bash/w /abc.txt' passwd -- 符合条件的行 被写入abc.txt 文件中 (如果不加-n会输出所有内容)
# 修改
7、 s/pattern/string -- 查找并替换,查找符合pattern模式的字符串,将其替换为string 适配(一、二、三、四、五)
s/pattern/string/g -- 全局查找并替换,查找符合pattern模式的字符串
s/pattern/string/2g -- 2g表示,同一行内,只替换前2个匹配的,剩下的不替换
s/pattern/string/ig -- 加i参数表示匹配时忽略大小写,g表示匹配到的全部替换
sed -i 's/root/Root/2g' passwd
sed -i 's/root/RooT/' passwd
sed -i 's/HADOOP/hadoop/2' str.txt
sed -i 's/hadoop/HADOOP/ig' str.txt
sed -n '/\/sbin\/nologin/=' passwd 只显示行号,不显示内容
# 其他编辑命令
8、= --- 显示行号
# 什么是反向引用?
&和\1 引用模式匹配的整个串
sed "s/1...e/&r/g" file 在file中搜寻以1开头,然后跟两个任意字符,以结尾的字符串
sed "s/\(1...e\)/\1r/g" file 和上面实现一样的功能,使用\1代表搜寻到的字符串
上面两种方式实现了一样的功能,分别使用&和\1引用前面匹配到的整个字符串
两者区别在于&只能表示匹配到的完整字符串,只能引用整个字符串;而\1可以使用()对匹配到的字符串
例如:如果我们仅想要提黄匹配到的字符串的一部分,name必须使用\1这种方式。
查找test.txt文件中以1开头,紧接着跟两个任意字符,再接一个e的字符串。将找到的字符串中开头的
sed "s/1\(...e\)/L\1/g" test.txt
将hadoop改为hadAAp
sed -i 's/had..p/HADOOP/g' str.txt 匹配所有以had开头,以p结尾的全局字符并替换成HADOOP
sed -i 's/had..p/&s/g' str.txt 匹配所有以had开头,以p结尾的全局字符并替换成 符合条件字符加上s
sed -i 's/\(had..ps\)/\1o/g' 等价上方表达式
sed -i 's/\(had\)...../\1doop/g' str.txt 匹配had后面五个任意字符的字符串并将匹配到的这五个字符替换为doop
# sed 中引用变量时注意事项
1)匹配模式中存在变量,则建议使用双引号 exapmle.sh
2)sed中需要引入自定义变量时,如果外面使用单引号,则自定义变量也必须使用单引号
# 利用sed查询特定内容
pattern 种类:
1、8p
2、8,10p
3、8,+5p
4、/regexp/p
5、/regexp_1/,/regexp_2/p
6、8,/reg/p
7、/reg/,8p
- 1、 打印file第20行内容
sed -n '20p' file
- 2、打印filezhong从第8行开始,到第15行结束的内容
sed -n '8,15p' file
- 3、打印file中从第8行开始,然后+5行的内容
sed -n '8,+5p' file
- 4、打印file中开头匹配hdfs字符串的内容
sed -n '/^hdfs/p' file
- 5、打印file中开头为root的行开始,到开头为hdfs的行结束的内容
sed -n '/^root/,/^hdfs/p' file
- 6、打印file中第8行开始,到含有/sbin/nologin的内容的行结束内容
sed -n '8,/\/sbin\/nologin/p' file
- 7、打印/etc/passwd中第一个包含/bin/bash内容的行开始,到第5行结束的内容
sed -n '/\/bin\/bash/,5p' /etc/passwd
example/sed mysql_process.sh
awk又叫做报告生成器,是一个文本从处理工具,通常用于处理数据并生成结果报告。由创始人Alfred Aho、Peter Weinberger和Brian Kernighan 姓氏的首个字母组成。
#awk内置变量
$0:一行,$1:冒号分隔的第一个 (root:x:0:0:root:/root:/bin/bash)
awk '{print $0}' ./str.txt
awk 'BEGIN{FS=":"}{print $1}' ./str.txt
awk '{print $1}' ./str.txt
awk '{print NF}' ./str.txt
awk '{print NR}' ./str.txt
awk '{print FNR}' ./str.txt ./list
awk 'BEGIN{FS="|"}{print $2}' ./list
awk 'BEGIN{FS=":"}{print $2}' ./list
awk 'BEGIN{FS=":";RS="---"}{print $2}' ./list
awk 'BEGIN{RS="---"}{print $0}' ./list
awk 'BEGIN{RS="--";FS="|"}{print $3}' ./list
awk 'BEGIN{RS="--";FS="|";ORS="&"}{print $3}' ./list
awk 'BEGIN{RS="--";FS="|";ORS="&"}{print $1,$3}' ./list
awk 'BEGIN{RS="--";FS="|";ORS="&"}{print $1 $3}' ./list
awk 'BEGIN{RS="--";FS="|";ORS="&";OFS=":"}{print $1,$3}' ./list
awk 'BEGIN{RS="--";FS="|";ORS="&";OFS="@@"}{print $1,$3}' ./list
awk '{print ARGC}' list
awk 'BEGIN{FS=":"}{printf "%20s %20s\n",$1,$7}' ./list
# 匹配/etc/passwd文件中含有root字符串的所有行
awk 'BEGIN{FS=":"}/root/{print $0}' /etc/passwd
# 匹配/etc/passwd文件中以yarn开头的所有行
awk 'BEGIN{FS=":"}/^yarn/{print $0}' /etc/passwd
# 使用awk计算/etc/services中的空白行数量
awk '/^$/{sum++}END{print sum}' ./example.sh
# 计算学生课程分数平均值,学生课程文件内容如下:
awk '{total=$2+$3+$4+$5;AVG=total/4;printf "%-8s%-5d%-5d%-5d%-8d%0.2f\n",$1,$2,$3,$4,$5,AVG}' ./student.txt
awk 'BEGIN{printf "%-8s%-8s%-8s%-8s%-8s%s\n","Name","Yuwen","Math","Englist","Pysical","Average"}{total=$2+$3+$4+$5;AVG=total/4;printf "%-8s%-8d%-8d%-8d%-8d%0.2f\n",$1,$2,$3,$4,$5,AVG}' ./student.txt
# 使用awk输出/etc/passwd文件行数。分两种方式显示行数,一种是正序如1,2,3,4
awk 'BEGIN{FS=":"}{if($3>50) print $0}' /etc/passwd
awk 'BEGIN{FS=":"}{if($3>50 && $3<100>) print $0}' /etc/passwd
awk 'BEGIN{FS=":"}{if($3>50 || $3<100>) print $0}' /etc/passwd
awk 'BEGIN{FS=":"}{if($3<50) printf "%s%d\n","小于50的UID",$3}' /etc/passwd
awk 'BEGIN{FS=":"}{if($3<50) printf "%-10s%-5d\n","小于50的UID",$3}' /etc/passwd
awk 'BEGIN{FS=":"}{if($3<50) printf "%-10s%-10s%-5d\n","小于50的UID",$1,$3}' /etc/passwd
awk 'BEGIN{FS=":"}{if($3<50) printf "%-10s%-10s%-5d\n","小于50的UID",$1,$3} else if($3>50 && $3<100){...}else{...}' /etc/passwd
awk -f script.awk /etc/passwd
awk -f while.awk
awk -f form.awk student.txt
# 1,以:为分隔符,返回/etc/passwd中每行中每个字段的长度
root:x:0:0:root:/root:/bin/bash
4:1:1:1:4:5:9
awk -f check_len.awk /etc/passwd
# 2,搜索字符串“I have a dream”中出现“ea”字符串的位置
awk 'BEGIN{str="I hava a dream";location=index(str,"ea");print location}'
awk 'BEGIN{str="I hava a dream";location=match(str,"ea");print location}'
# 3,将字符串“Hadoop is a bigdata Framaword”全部转换为小写、大写
awk 'BEGIN{str="Hadoop is a bigdata Framework";print tolower(str);print toupper(str)}'
# 5,将字符串“Hadoop Kafka Spark Storm HDFS YARN Zookeeper”,按照空格分隔符,分隔每部分保存到数组array中
awk 'BEGIN{str="Hadoop Kafka Spark Storm HDFS YARN Zookeeper";split(str,arr);for(a in arr) print arr[a]}'
# 6,搜索字符串“Tranction 2345 Start:Select * from master”第一个数字出现的位置
awk 'BEGIN{str="Tranction 2345 Start:Select * from master";location=match(str,/[0-9]/);print location}'
# 7,截取字符串“transaction start”的子串,截取条件从第4个字符开始,截取5位
awk 'BEGIN{str="transaction start";print substr(str,4,5)}'
awk 'BEGIN{str="transaction start";print substr(str,4)}'
# 8,替换字符串“Tranction 243 Start,Event ID:9002”中第一个匹配到的数字串为$符号
awk 'BEGIN{str="Tranction 243 Start,Event ID:9002";count=sub(/[0-9]+/,"$",str);print count,str}'
awk 'BEGIN{str="Tranction 243 Start,Event ID:9002";count=gsub(/[0-9]+/,"$",str);print count,str}'
num1=20
var="hello world"
awk -v num2=$num1 -v var1="$var" 'BEGIN{print num2,var1}' #20 hello world
array=("Allen" "Mike" "Messi" "Jerry" "Hanmeimei" "Wang")
echo ${array[2]}
echo ${array[0]}
echo ${#array[@]}
echo ${#array[*]}
str="test string"
echo $str
echo ${#str}
echo ${#array[4]}
array[1]="Jerry"
echo ${array[1]}
echo ${array[@]}
unset array[0]
echo ${array[*]}
echo ${array[@]}
echo ${array[@]:1:3}
echo ${array[@]:1}
echo ${array[@]/e/E}
for a in ${array[@]};do echo $a;done
###需求描述,利用awk处理日志,并生成结果报告
record_len.awk