脚本宝典收集整理的这篇文章主要介绍了

跟着360架构师学shell

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。

1. 变量替换

  • ${变量名#匹配规则}  从头开始匹配,最短删除
  • ${变量名##匹配规则}  从头开始匹配,最长删除
  • ${变量名%匹配规则}  从尾开始匹配,最短删除
  • ${变量名%%匹配规则}  从尾开始匹配,最长删除
  • ${变量名/旧字符串/新字符串}  替换旧的字符串为新字符串,只替换第一个
  • ${变量名//旧字符串/新字符串}  替换旧的字符串为新字符串,替换所有

例:

variable_1="i love u, do you love me"  echo ${variable_1#*ov} # e u, do you love me  echo ${variable_1##*ov} # e me  echo ${variable_1%ov*} # i love u, do you l  echo ${variable_1%%ov*} # i l  echo ${variable_1/ov/bb} # i lbbe u, do you love me  variable_1="i love u, do you love me" variable_2=${variable_1/ov/bb} echo $variable_2 # i lbbe u, do you lbbe me

2. 字符串处理

2.1 获取字符串长度

例:

variable_1="i love u, do you love me" echo ${#variable_1} expr length "$variable_1"  len=`expr length "$variable_1"` echo $len

2.2 获取子串在字符串中的索引位置

  • expr index "$string" "$substring"  [不是子串,而是子串切分成单个字符,查找第一个出现的字符的位置]

例:

variable_1="i love u, do you love me" variable_2="ov" expr index "$variable_1" "$variable_2" # 4  variable_2="ok" expr index "$variable_1" "$variable_2" # 4

2.3 获取子串长度

  • expr match "string substring"  [必须从头开始匹配,能匹配到的子串返回长度,支持正则]

例:

variable_1="quickstart is a app"  echo `expr match "$variable_1" app` # 0  echo `expr match "$variable_1" quick` # 5  echo `expr match "$variable_1" quick.` # 6  echo `expr match "$variable_1" quick.*` # 19

2.4 子串抽取

  • ${string:position}  从string的position位置开始
  • ${string:position:length}  从position位置开始抽取length长度
  • ${string:-position}  从右边开始匹配
  • ${string:(position)}  从左边开始匹配
  • expr substr "$string" "$position" "$length"  从position位置开始抽取length长度,索引从0开始

注意:${string:position}索引从1开始,而 expr 索引从0开始

例:

variable_1="i love u, do you love me" position=4 length=4 echo ${variable_1:position} # ve u, do you love me  echo ${variable_1:position:length} # ve u  echo ${variable_1: -position} # e me  echo ${variable_1:(-position)} # ve u, do you love me  echo ${variable_1:(-position)} # e me  variable_2=`expr substr "$variable_1" "$position" "$length"` echo $variable_2 # ove

3. 字符串练习

string="bigdata process framework is hadoop, hadoop is an open source project"  执行脚本后,打印输出string字符串变量,并给出用户以下选项: (1) 打印string长度 (2) 在整个字符串中删除Hadoop (3) 替换第一个Hadoop为Mapreduce (4) 替换全部Hadoop为Mapreduce 用户输入对应的数字会执行相应的功能,输入q|Q退出操作
#!/bin/bash string="Bigdata process framework is Hadoop,Hadoop is an open source project"  function print_tips {     echo "******************************************"     echo "***  (1) 打印string长度"     echo "***  (2) 在整个字符串中删除Hadoop"     echo "***  (3) 替换第一个Hadoop为Mapreduce"     echo "***  (4) 替换全部Hadoop为Mapreduce"     echo "******************************************" }  function print_len {     echo "${#string}" }  function del_Hadoop {     echo "${string//Hadoop/}" }  function rep_Hadoop_to_Mapreduce_first {     echo "${string/Hadoop/Mapreduce}" }  function rep_Hadoop_to_Mapreduce_alll {     echo "${string//Hadoop/Mapreduce}" }  while true do     echo     echo     echo "【string=$string】"     print_tips      read -p "please input your choice(1|2|3|4|q|Q): " choice      case $choice in             1)                     echo                     print_len                     ;;             2)                     echo                     del_Hadoop                     ;;             3)                     echo                     rep_Hadoop_to_Mapreduce_first                     ;;             4)                     echo                     rep_Hadoop_to_Mapreduce_alll                     ;;             q|Q)                     exit                     ;;             *)                     echo                     echo "error input!"                     ;;     esac done

4. 命令替换

  • `command`
  • $(command)

$(())主要用来进行整数运算,包括加减乘除

例1:获取系统中的所有用户并输出(/etc/passwd)

cat /etc/passwd | cut -d ":" -f 1  #!/bin/bash  index=1  for user in `cat /etc/passwd | cut -d ":" -f 1` do     echo "this is $index user: $user"     index=$(($index+1)) done

例2:根据系统时间计算今年、明年

echo "this is $(date +%Y), next year is $(($(date +%Y)+1))"

例3:根据系统时间获取今年还剩下多少个星期,已经过了多少个星期

echo "今年已经过了$(date +%j)天,合$(($(date +%j) / 7))周,还剩下$(((365-$(date +%j)) / 7))周"

例子4:判断nginx进程是否存在,不存在的话拉起该进程

#!/bin/bash  nginx_process_num=$(ps -ef | grep nginx | grep -v grep | wc -l) if [ $nginx_process_num -eq 0 ]; then     systemctl start nginx fi

5. 有类型变量

  • declare、typeset
-r 只读 -i 整数 -a 数组 -f 在脚本中显示定义的函数和函数体 -F 在脚本中显示定义的函数 -x 环境变量

如果要取消类型声明,减号变加号就行了

例:

declare -r variable_1="hello java" variable_1="abc"  num1=10 echo $num1+1  declare -i num2=10 declare -i num3 num3=$num2+1  echo $num2+1 echo $num3  declare -f declare -F  array=("jane" "jone" "jack" "jordan") 输出数组内容     echo ${array[@]}    输出所有内容     echo ${array[0]}    输出下标对应的内容 获取数组长度     echo ${#array}     echo ${#array[0]}

6. 数字运算

  • expr $num1 operator $num2
  • $(($num1 operator $num2))

注意:expr只支持整型运算

  • expr 操作符
num1 | num2     num1不为空且不为0,返回num1,否则返回num2 num1 & num2     num1不为空且不为0,返回num1,否则返回0 num1 < num2     num1小于num2,返回1,否则返回0 num1 <= num2    num1小于等于num2,返回1,否则返回0 num1 = num2     num1等于num2,返回1,否则返回0 num1 != num2    num1不等于num2,返回1,否则返回0 num1 > num2     num1大于num2,返回1,否则返回0 num1 >= num2    num1大于等于num2,返回1,否则返回0 num1 + num2 num1 - num2 num1 * num2 num1 / num2 num1 % num2

例:

num1=10 num2=20  expr $num1 + $num2 echo $(($num1 + $num2))  expr $num1 | $num2 expr $num1 & $num2 expr $num1 > $num2 expr $num1 >= $num2 expr $num1 < $num2 expr $num1 <= $num2 expr $num1 = $num2 expr $num1 + $num2 expr $num1 - $num2 expr $num1 * $num2 expr $num1 / $num2 expr $num1 % $num2

练习:提示用户输入一个正整数num,然后计算1+2+3+...+num的值,必须判断num是否为正整数,不符合允许再次输入

#!/bin/bash  sum=0 while true do     read -p "please input: " num     expr $num + 1 &> /dev/null      if [ $? -eq 0 ]; then         if [ `expr $num > 0` -eq 1 ]; then              for ((i=0;i<=$num;i++))             do                 sum=$(($sum + $i))             done              echo $sum             exit         else             echo "小于等于0"             continue         fi     else         echo "不是整数"         continue     fi done

7. 函数定义和使用

7.1 函数定义

function name { } name() { }

例:写一个nginx的守护脚本

#!/bin/bash  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                 echo "starting!"                 systemctl nginx start                 sleep 1         fi done

7.2 传递参数

例:写一个脚本支持+-*/四种运算

#!/bin/bash  function cal {     case $2 in         +)             echo $(($1 + $3))             ;;         -)             echo $(($1 - $3))             ;;         *)             echo $(($1 * $3))             ;;         /)             echo $(($1 / $3))             ;;         *)             echo "error input!"             ;;     esac }  cal $1 $2 $3

7.3 返回值

  • return返回值,只能返回1-255之内的整数。使用return返回值,通常供其他地方调用获取状态,因此通常返回0或者1,0表示成功,1表示失败。return表示return 0
  • echo返回值,可以返回任何字符结果,通常用于返回数据,比如一个字符串或列表值

例:

#!/bin/bash  this_pid=$$ function is_nginx_running {          ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/null      if [ $? -eq 0 ]; then         return     else         return 1     fi }  is_nginx_running && echo "nginx is running" || echo "nginx is down"  sh -x nginx_stat.sh        [-x可以查看执行过程]  #!/bin/bash function get_user_list {     users=$(cat /etc/passwd | cut -d ":" -f1)     echo $users }  index=1 user_list=$(get_user_list) for u in $user_list do     echo "this is the $((index++)) user: $u" done

7.4 变量

  • 使用local定义变量表示局部变量,否则一般的变量都是全局变量
  • 函数内部的变量如果跟外部变量同名,则函数内部的变量替换外部的变量

7.5 函数库

例:定义一个函数库,该函数库实现以下几个函数

(1)加法函数 add (2)减法函数 reduce (3)乘法函数 multiple (4)除法函数 dived (5)打印系统运行情况的函数sys_load,该函数可以显示系统内存运行情况
base_function.lib  #!/bin/echo function add {     echo "`expr $1 + $2`" } function reduce {     echo "`expr $1 - $2`" } function multiple {     echo "`expr $1 * $2`" } function divide {     echo "`expr $1 / $2`" } function sys_load {     echo "---memory info---"     free -m      echo     echo "---disk info---"     df -h }
calculate.sh  #!/bin/bash . /root/script/base_function.lib  add 1 2 reduce 11 33 multiple 3 44 divide 20 2 sys_load
  • 库文件的后缀是任意的,但是一般以.lib使用
  • 库文件通常没有执行权限

8. 常用查找命令

8.1 find [路径] [选项] [操作]

选项

-name                根据名字 -iname                根据名字,不区分大小写 -perm                根据权限 -prune                该选项可以排除某些查找目录 -user                 根据文件用主 -group                根据文件属组 -mtime -n|+n  根据文件更改时间,-n表示n天以内修改的文件,+n表示n天意外修改的文件 -mmin -n|+n   根据文件更改时间,-n表示n分钟以内修改的文件,+n表示n分钟意外修改的文件 -newer file1 ! file2     比file1新但是比file2旧的文件 -type                 根据文件类型    f-文件,d-目录,l-管道文件 -size -n +n             根据文件大小 -mindepth n             从n级子目录开始搜索 -maxdepth n             最多搜索到n级子目录 -a                 与 -o                 或 !|-not                 非

操作

-print         默认操作 -exec        对搜索到的文件执行特定操作,格式为 -exec command {} ; ,其中{}代表搜索到的文件,如:find . -name "*.conf" -exec rm -rf {} ; -ok        跟-exec一样,只是每次操作都会给用户提示

例:将/var/log目录下以log结尾,且更改时间在7天以上的删除

find /var/log -name "*log" -mtime +7 -exec rm -rf {} ;

8.2 locate which whereis

locate         不同于 findfind会查找整个磁盘,而locate命令会在数据库中查找,只能查找单个文件。可以用updatedb更新数据库文件,该文件是 /var/lib/mlocate/locate.db whereis        -b,只返回二进制文件,-m,只返回帮助文档文件,-s,只返回源码文件 which         只查找二进制文件

9. grep

  • grep [option] [pattern] [file1,file2]
  • command | grep [option] [pattern]

参数

-i     不区分大小写 -v     反向选择 -n     显示行号 -r     递归 -E     支持扩展正则表达式 -F     不按正则表达式,按字符串字面匹配 -x     匹配整行 -w     匹配整词 -c     只输出匹配到的总行数,不显示具体内容 -l     只列出文件,不显示具体内容

例:grep -E "python|PYTHON" file

egrep 和 grep -E 等价

10. sed(stream editor缩写)

10.1 sed

  • sed [option] "pattern command" file
  • stdout | sed [option] "pattern command" file

option

-n     只打印模式匹配行。sed -n "/python/p" sed.txt -e     直接在命令行编辑。sed -n -e "/PYTHON/p" -e "/python/p" sed.txt,多重处理的时候用-e连接 -f     指定编辑处理的 pattern command 内容。sed -n edit.sed sed.txt,edit.sed中的内容是/python/p -r     pattern支持扩展正则表达式。sed -n -r "/python|PYTHON/p" sed.txt -i     对源文件进行修改

例:替换文件中love为like

sed -n "s/love/like/g;p" sed.txt sed -i "s/love/like/g" sed.txt

pattern

10command            匹配第1010,20command            匹配第10-2010,+5command            匹配第10-16/pattern1/command        匹配pattern1的行。sed -n "//spool//p" /etc/passwd,匹配带有/spool/的行。sed -n "/^daemon/p" /etc/passwd,匹配daemon开头的行 /pattern1/,/pattern2/command     匹配pattern1到pattern2的行结束。sed -n "/^daemon/p" /etc/passwd 10,/pattern1/command        从第10行开始匹配到第一个pattern1的行结束 /pattern1/,10command        连续匹配10

command

查询     p     打印 增加     a     行后追加。sed -i "//bin/bash/a this user can login to system" passwd     i     行前追加     r     外部文件读入,行尾追加     w     匹配行写入外部文件 删除     d     删除不能登录的用户,sed -i "//sbin/nologin/d" passwd。删除从mail开头的行到ftp开头的行,sed -i "/^mail/,/^ftp/d" passwd     例:删除配置文件中的所有空行和注释行。sed -i "/^$/d;/[:blank:]*#/d;/t/d" nginx.conf,[:blank:]匹配空格,t匹配tab     例:在配置文件中所有不以#开头的行前面添加*符号(#开头的行不添加)。sed -i "s/^([^#])/*1/g" nginx.conf 或者 sed -i "s/^[^#]/*&/g" nginx.conf 更改     s/old/new/         将行内第一个替换     s/old/new/g     将行内所有替换     s/old/new/2     将行内第二个替换     s/old/new/2g     从第二个开始替换所有的     s/old/new/ig     忽略大小写     例:删掉所有的数字。sed -i "s/[0-9]+//g" sed.txt 其它     =        显示行号。sed -n "//sbin/nologin/=" passwd

10.2 反向引用

  • & 和 1 引用模式匹配到的整个串(1的时候要替换的模式匹配中的串要用小括号包围起来)

例:sed -i "s/had..p/&s/g" sed.txt   给能匹配到had..p的字符串后面加上s,hadoopx -> hadoopsx

sed -i "s/ha(d..p)/XX1/g" sed.txt     给能匹配到had..p的d..p之外的串全替换成上XX,hadoopx -> XXdoopx

例:统计mysql配置文件各配置段的数量

#!/bin/bash  FILE_NAME=/root/script/my.cnf function get_all_segament {     sed -n '/[.*]/p' $FILE_NAME | sed -e "s/[//g" | sed -e "s/]//g"     # 查找[开头]结尾的行,并且删除掉[和] }  function get_all_segament_count {     count=`sed -n "/[$1]/,/[.*]/p" $FILE_NAME | grep -v "^#" | grep -v "^$" | grep -v "[.*]" | wc -l`     # 查找[$1]开头的行到发现[.*]的行结束,去掉#开头和空行,并去掉[.*]的行(即开头和结束的行),统计数量     echo $count }  index=0 for segament in $(get_all_segament) do     index=`expr $index + 1`     count=`get_all_segament_count $segament`     echo "$index: $segament $count" done  输出: 1: client 1 2: mysql 1 3: mysqld 6 4: mysqldump 3

11. awk

  • awk 'BEGIN{}pattern{commands}END{}' file_name
  • stdout | 'BEGIN{}pattern{commands}END{}'
BEGIN{}        正式处理之前执行的 pattern     匹配模式 {commands}     执行命令(可能多行) END{}         处理完所有的匹配数据之后执行

11.1 内置变量

$0        整行内容 $1-$n        本行中按照某个字符分隔后的第n个变量 NF        当前行的字段个数,也就是列的个数(Number Field) NR         当前行的行号,从1开始计算(Number Row) FNR        多文件处理时,每个文件行号单独计数,都是从1开始(File Number Row) FS        输入字段分隔符,不输入默认是空格或者tab键分隔(Field Separator) RS        输入行分隔符。默认回车换行(Row Separator) OFS        输出字段分隔符。默认空格 ORS        输出行分隔符。默认回车 FILENAME 处理的文件名 ARGC        命令行参数个数 ARGV        命令行参数数组

例:打印/etc/passwd文件的内容

awk '{print $0}' /etc/passwd awk 'BEGIN{FS=":"}{print $1}' /etc/passwd awk 'BEGIN{FS=":"}{print NF}' /etc/passwd awk '{print NR}' /etc/passwd nginx.conf awk '{print FNR}' /etc/passwd nginx.conf awk 'BEGIN{RS="--"}{print $0}' test.txt echo "a-b-c--d-e-f--g-h-i" | awk 'BEGIN{RS="--";FS="-"}{print $3}' echo "a-b-c--d-e-f--g-h-i" | awk 'BEGIN{RS="--";FS="-";ORS="|";OFS="&"}{print $1,$2,$3}' #必须用逗号分隔,否则输出字段分隔符不会起作用。a&b&c|d&e&f|g&h&i awk '{print FILENAME}' nginx.conf #文件有多少行就会输出多少次 awk '{print ARGC}' /etc/passwd test.txt

11.2 printf 格式化输出

%s         打印字符串 %d         打印十进制数字 %x         打印十六进制 %f         打印浮点型 %o         打印八进制 %e         打印科学计数法 %c         打印ascii码 -        左对齐 +         右对齐 #         显示八进制在前面加0,十六进制在前面加0x

例:

awk 'BEGIN{FS=":"}{printf "%sn",$1}' /etc/passwd awk 'BEGIN{FS=":"}{printf "%-20s %-20sn",$1,$7}' /etc/passwd awk 'BEGIN{FS=":"}{printf "%#on",$3}' /etc/passwd

11.3 模式匹配的两种方式

  • 正则表达式
  • 按关系运算符匹配
> < ==        可以用于数值和字符串 <= >= != ~        匹配正则表达式 !~         不匹配正则表达式 && || !

例:

匹配/etc/passwd中包含root的行。    awk '/root/{print $0}' /etc/passwd 匹配/etc/passwd中以root开头的行。    awk '/^root/{print $0}' /etc/passwd  匹配/etc/passwd中第3个字段大于50的行。    awk 'BEGIN{FS=":"}$3>50{printf "%sn",$0}' /etc/passwd  匹配/etc/passwd中第7个字段等于/sbin/nologin的行。    awk 'BEGIN{FS=":"}$7=="/sbin/nologin"{printf "%sn",$7}' /etc/passwd  匹配/etc/passwd中第7个字段不等于/sbin/nologin的行。    awk 'BEGIN{FS=":"}$7!="/sbin/nologin"{printf "%sn",$7}' /etc/passwd  匹配/etc/passwd中第3个字段包含三个以上数字的行(匹配正则表达式)。    awk 'BEGIN{FS=":"}$3~/[0-9]{3,}/{printf "%dn",$3}' /etc/passwd  匹配/etc/passwd中包含root或nologin的所有行。awk '/root/ || /nologin/{print $0}' /etc/passwd  匹配/etc/passwd中第3个字段包含小于50并且第4个字段大于60并且第7行包含/sbin/nologin的所有行     awk 'BEGIN{FS=":"}$3>50 && $4<60 && $7~//sbin/nologin/{printf "%s %s %sn",$3,$4,$7}' /etc/passwd

11.4 动作表达式中的算术运算符

+ - *  ^或**    乘方 ++x x++ --x x--

例:

awk 'BEGIN{var1=10;var2="hello";print var1,var2}' awk 'BEGIN{num1=10;num2+=num1;print num1,num2}' awk 'BEGIN{num1=10;num2=29;print num1+num2}' awk 'BEGIN{num1=10;num2=29;print num1-num2}' awk 'BEGIN{num1=10;num2=29;print num1*num2}' awk 'BEGIN{num1=10;num2=29;print num1/num2}' awk 'BEGIN{num1=10;num2=29;print num1^num2}' awk 'BEGIN{x=10;y=20;print x++;y++}' awk 'BEGIN{x=10;y=20;print ++x;++y}' awk 'BEGIN{num1=10;num2=29;printf "%0.2fn",num1/num2}' #保留两位小数

例:使用awk计算某文件中空白行的数量

awk '/^$/{sum++}END{print sum}' my.cnf

例:计算课程分数平均值

Allen     90 99 93 73 Jone     83 23 38 97 Monica     99 77 89 43 Jerry     77 44 32 91  awk 'BEGIN{printf "%-8s %-8s %-8s %-8s %-8sn","姓名","语文","数学","物理","平均分"}{total=$2+$3+$4+$5;avg=total/4;printf "%-8s %-8d %-8d %-8d %-8d %0.2fn",$1,$2,$3,$4,$5,avg}' score.txt

11.5 条件

if (条件表达式1)     动作1 else if (条件表达式2)     动作2 else     动作3

例:

awk 'BEGIN{FS=":"}{if($3<50) {printf "%-10s %-4dn","小于50的uid",$3} else if($3<80) {printf "%-10s %-4dn","小于80的uid",$3} else {printf "%-10s %-4dn","其它uid",$3}}' /etc/passwd

awk的代码可能很长,这个时候可以写成脚本用-f来调用

BEGIN {     FS=":" }  {     if($3<50) {         printf "%-10s %-4dn","小于50的uid",$3     } else if($3<80) {         printf "%-10s %-4dn","小于80的uid",$3     } else {         printf "%-10s %-4dn","其它uid",$3     } }  awk -f script.awk /etc/passwd

例:计算课程分数平均值,并且只打印分数大于70的同学的姓名和分数

Allen     90 99 93 73 Jone     83 23 38 97 Monica     99 77 89 43 Jerry     77 44 32 91  awk '{total=$2+$3+$4+$5;avg=total/4;if(avg>70){printf "%-10s %-0.2fn",$1,avg}}' score.txt

11.6 循环

while(条件表达式)     动作  do     动作 while(条件表达式)  for(初始化计数器;测试计数器;计数器变更)     动作

例:计算1+2+3+...+100的和,分别使用do-while、while、for实现

awk 'BEGIN{for(i=1;i<=100;i++){sum+=i};printf "sum=%dn",sum}' awk 'BEGIN{do{sum+=i++}while(i<=100);printf "sum=%dn",sum}' awk 'BEGIN{while(i<=100){sum+=i++};printf "sum=%dn",sum}'

11.7 字符串函数

函数名                   解释         函数返回值 ----------------------------------------------------------------------------------------------------------- length(str)            计算字符串长度                                                 整数返回值 index(str1,str2)         在str1中查找str2的位置                                         返回值为索引,从1开始 toupper(str)             转换为大写                                                     转换后的大写字符串 tolower(str)             转换为小写                                                     转换后的小写字符串 substr(str,m,n)         从str的m个字符截取n位                                             截取后的子串 split(str,arr,fs)         按fs切割字符串,结果保存到arr(分隔符默认是空格,可以省略)         切割后的子串的个数 match(str,RE)             在str中按照RE查找,返回位置                                     返回索引位置,从1开始  sub(RE,RepStr,str)        在str中按RE搜索字符串并将其替换为RepStr,只替换第一个,返回替换的个数 gsub(RE,RepStr,str)        在str中按RE搜索字符串并将其替换为RepStr,替换所有

例:

awk 'BEGIN{print length("abcd")}' awk 'BEGIN{print index("abcd","c")}' awk 'BEGIN{print toupper("abCd")}' awk 'BEGIN{print tolower("abCd")}'  awk 'BEGIN{print substr("hello,world",3,6)}' awk 'BEGIN{print split("root:x:0:0:root",arr,":");print arr}' awk 'BEGIN{print match("hello,world", /lo/)}'

例:返回/etc/passwd中每个字段的长度

awk 'BEGIN{FS=":";OFS=":"}{print length($1),length($2),length($3),length($4),length($5),length($6),length($7)}' /etc/passwd  搜索"i have a dream"中ea的位置 awk 'BEGIN{print index("i have a dream","ea")}' awk 'BEGIN{print match("i have a dream","ea")}'  将"Hadoop is a bigdata framework"转换为小写 awk 'BEGIN{print tolower("Hadoop is a bigdata framework")}'  将"Hadoop is a bigdata framework"转换为大写 awk 'BEGIN{print toupper("Hadoop is a bigdata framework")}'  将"Hadoop is a bigdata framework"按空格分割后保存在数组中 awk 'BEGIN{str="Hadoop is a bigdata framework";split(str,arr," ");for(a in arr){print arr[a]}}'  找出字符串"Transaction 23345 start: select * from master"中第一个数字出现的位置  awk 'BEGIN{str="Transaction 23345 start: select * from master";print match(str,/[0-9]/)}'  截取字符串"Transaction 23345 start: select * from master",从第4个开始截取5位 awk 'BEGIN{str="Transaction 23345 start: select * from master";print substr(str,4,5)}'  替换"Transaction 23345 start, Event ID: 9002"中出现的第一个数字串为$ awk 'BEGIN{str="Transaction 23345 start, Event ID: 9002";count=sub(/[0-9]+/,"$",str);print count,str}'

11.8 选项

-v     参数传递 -f     指定awk脚本文件 -F     指定分隔符,可以连着写 -V     查看awk版本

例:

awk -v arg1=12 -v arg2="hello world" 'BEGIN{print arg1,arg2}' awk -F ":" '{print $1}' /etc/passwd awk -F: '{print $1}' /etc/passwd

11.9 awk中数组的用法

  • 数组使用(索引从0开始)
array=("janee" "jone" "jacek" "jordan") 打印元素             echo ${array[0]}、echo ${array[@]} 打印元素个数         echo ${#array[@]} 打印元素长度         echo ${#array[0]} 给元素赋值        array[2]="messi" 删除元素            unset array[2]、unset array 分片访问            echo ${array[0]:1:3} 元素替换            ${array[@]/e/E}(替换元素中的第一个e为E)、${array[@]//e/E}(替换元素中的所有e为E) 元素便利            for a in ${array[@]}; do echo $a; done
  • awk中数组的用法(索引从1开始)
awk 'BEGIN{str="hadoop spark yarn storm flume";split(str,array," ");for(i=1;i<=length(array);i++){print array[i]}}'  awk的数组中可以使用字符串作为数组的下标 awk 'BEGIN{array["var1"]="zhangsan";array["var2"]="lisi";array["var3"]="wangwu";for(i in array){print array[i]}}'

例:统计各种tcp状态连接状态数

netstat -an | grep tcp | awk '{array[$6]++}END{for(i in array){print i,array[i]}}'

例:计算纵向横向总和

Allen     90 99 93 73 Jone     83 23 38 97 Monica     99 77 89 43 Jerry     77 44 32 91  awk '{line++;line_sum=0;for(i=1;i<=NF;i++){line_sum+=$i;col_sum[i]+=$i;printf "%-6s ",$i};print line_sum}END{printf "%-6s","";for(i=2;i<=length(col_sum);i++){printf "%-6s ",col_sum[i]};printf "n"}' score.txt  输出: Allen   90     99     93     73     355 Jone    83     23     38     97     241 Monica  99     77     89     43     308 Jerry   77     44     32     91     244        349    243    252    304 

11.10 awk中数组的用法

例:用awk脚本处理数据并生成报告

生成数据的脚本:insert.sh  #!/bin/bash function create_random {     min=$1     max=$(($2-$min+1))     num=$(date +%s%N)     echo $(($num%$max+$min)) }  INDEX=1 while true do     for user in Mike Allen Jerry Tracy Hanmeimei Lilei     do         COUNT=$RANDOM         NUM1=`create_random 1 $COUNT`         NUM2=`expr $COUNT - $NUM1`         echo "`date "+%Y-%m-%d %H:%M:%S"`" $INDEX Batches: $user insert $COUNT data into table 'test1', insert $NUM1 records successfully, failed insert $NUM2 records >> /root/script/data.txt         INDEX=`expr $INDEX + 1`     done done  数据格式: 2019-04-17 23:44:36 495 Batches: Jerry insert 7658 data into table test1, insert 1008 records successfully, failed insert 6650 records 2019-04-17 23:44:36 496 Batches: Tracy insert 17609 data into table test1, insert 10348 records successfully, failed insert 7261 records 2019-04-17 23:44:36 497 Batches: Hanmeimei insert 14256 data into table test1, insert 1599 records successfully, failed insert 12657 records 2019-04-17 23:44:36 498 Batches: Lilei insert 9279 data into table test1, insert 7856 records successfully, failed insert 1423 records 2019-04-17 23:44:36 499 Batches: Mike insert 22652 data into table test1, insert 6291 records successfully, failed insert 16361 records  (1)、统计每个人员插入了多少条数据进数据库 awk 'BEGIN{printf "%-10s %-10sn","name","total"}{stat[$5]+=$7}END{for(i in stat){printf "%-10s %-10sn",i,stat[i]}}' data.txt  (2)、统计每个人员插入成功和失败了多少条数据进数据库 awk 'BEGIN{printf "%-10s %-10s %-10s %-10sn","User","Total","Succeed","Failed"}{sum[$5]+=$7;suc_sum[$5]+=$13;fail_sum[$5]+=$18}END{for(i in sum){printf "%-10s %-10s %-10s %-10sn",i,sum[i],suc_sum[i],fail_sum[i]}}' data.txt  (3)、在(2)的基础上统计全部插入记录数 awk 'BEGIN{printf "%-10s %-10s %-10s %-10sn","User","Total","Succeed","Failed"}{sum[$5]+=$7;suc_sum[$5]+=$13;fail_sum[$5]+=$18}END{for(i in sum){all_sum+=sum[i];all_suc_sum+=suc_sum[i];all_fail_sum+=fail_sum[i];printf "%-10s %-10s %-10s %-10sn",i,sum[i],suc_sum[i],fail_sum[i]};printf "%-10s %-10s %-10s %-10sn","",all_sum,all_suc_sum,all_fail_sum}' data.txt  (4)、查找丢失数据,也就是成功+失败的记录数不等于总共插入的记录数 awk '{if($7!=$13+$18){print $0}}' data.txt

12. mysql操作

12.1 安装启动mariadb

yum install mariadb mariadb-server mariadb-libs -y systemctl start mariadb

13. 脚本工具

脚本工具功能概述 (1)、实现一个脚本,该脚本提供类似supervisor的功能,可以对进程进行管理 (2)、一键查看所有进程运行状态 (3)、单个或批量启停进程 (4)、提供进程分组功能,可以按组查看进程运行状态,可以按组启停进程
配置文件 process.cfg  [GROUP_LISE] WEB_LIST DB_LIST HADOOP_LIST YARN_LIST  [WEB_LIST] nginx httpd  [DB_LIST] mysql postgresql  [HADOOP_LIST] datanode namenode  [YARN_LIST] resourcemanager nodemanager  [nginx] description="Web Server 1" program_name=tail parameter=-f /root/tmp/web-nginx.conf   [httpd] description="Web Server 2" program_name=tail parameter=-f /root/tmp/web-httpd.conf  [mysql] description="High Perfrmance Database" program_name=tail parameter=-f /root/tmp/db-mysql.conf  [postgresql] description="High Perfrmance Database" program_name=tail parameter=-f /root/tmp/db-postgresql.conf  [datanode] description="Hadoop datanode" program_name=tail parameter=-f /root/tmp/hadoop-datanode.conf  [namenode] description="Hadoop namenode" program_name=tail parameter=-f /root/tmp/hadoop-namenode.conf  [resourcemanager] description="yarn resourcemanager" program_name=tail parameter=-f /root/tmp/yarn-resourcemanager.conf  [nodemanager] description="yarn nodemanager" program_name=tail parameter=-f /root/tmp/yarn-nodemanager.conf
#!/bin/bash  THIS_PID=$$ GROUP_LIST=GROUP_LIST CFG_FILE=/root/script/tmp/process.cfg  function group_list {         group_list=`sed -n "/[$GROUP_LIST]/,/^[.*]/p" $CFG_FILE | grep -v "^$" | grep -v "[.*]" | grep -v "#"`         echo $group_list }  function get_all_process {         for group in $(group_list)         do                 p_list=$(get_all_process_by_group $group)                 echo $p_list         done }  function get_all_process_by_group {         group_process=`sed -n "/[$1]/,/[.*]/p" $CFG_FILE | grep -v "^$" | grep -v "[.*]" | grep -v "#"`         echo $group_process }  function is_group_exists {         count=`sed -n "/[$1]/p" $CFG_FILE | grep -v "$GROUP_LIST" | wc -l`         if [ $count -eq 1 ]; then                 return 0         else                 return 1         fi }  function get_group_by_process_name {         for g in $(group_list)         do                 for p in `get_all_process_by_group $g`                 do                         if [ $p == $1 ]; then                                 echo "$g"                         fi                 done         done }  function get_process_info_by_pid {         ps -ef | awk -v pid=$1 '$2==pid{print}' &> /dev/null         if [ $? -eq 0 ]; then                 proc_status="RUNNING"         else                 proc_status="STOPPED"         fi          proc_cpu=`ps aux | awk -v pid=$1 '$2==pid{print $3}'`         proc_mem=`ps aux | awk -v pid=$1 '$2==pid{print $4}'`         proc_start_time=`ps -p $1 -o lstart | grep -v "STARTED"` }  function get_pid_by_process_name {         if [ $# -ne 1 ]; then                 return 1         else                 pid=`ps -ef | grep "$1" | grep -v grep | grep -v "$0" |  awk '{print $2}'`                 echo $pid         fi }  function format_print {         group=`get_group_by_process_name $1`         ps -ef | grep $1 | grep -v grep | grep -v $THIS_PID &> /dev/null         if [ $? -eq 0 ]; then             for pids in `get_pid_by_process_name $1`             do                 for _pid in $pids                 do                     get_process_info_by_pid $_pid                      awk -v p_name="$1"                      -v p_group="$group"                      -v p_id="$_pid"                      -v p_status="$proc_status"                      -v p_cpu="$proc_cpu"                      -v p_mem="$proc_mem"                      -v p_start_time="$proc_start_time"                      'BEGIN{printf "%-20s%-10s%-10s%-10s%-10s%-10s%-10sn",p_name,p_group,p_status,p_id,p_cpu,p_mem,p_start_time;}'                 done             done         else                     awk -v p_name="$1"                      -v p_group="$group"                      'BEGIN{printf "%-20s%-10s%-10s%-10s%-10s%-10s%-10sn",p_name,p_group,"NULL","NULL","NULL","NULL","NULL";}'         fi }  echo "********************************************************************************************************" echo `group_list`  echo `get_all_process`  echo `get_all_process_by_group DB_LIST`  echo `is_group_exists WEB_LIST`  echo $(get_group_by_process_name mariadb)  format_print $1 echo "********************************************************************************************************"

14. 其它

ps -ef | grep nginx | awk '{print $2}' | xargs kill  $?        命令执行的结果,0表示成功,其它表示有异常 $$        脚本执行的子进程的pid $#         参数数量 $0      shell文件名 $@      shell执行的时候传入的所有参数 shift    shell执行的时候跳过一个传入的参数
netstat     -l[listening]     -a[all]     -t[tcp]     -p[program] Show the PID and name of the program to which each socket belongs.

总结

以上是脚本宝典为你收集整理的

跟着360架构师学shell

全部内容,希望文章能够帮你解决

跟着360架构师学shell

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过