Shell脚本实践总结

对比大小

符号用法:(必须使用双括号)

< 小于     (( "$a" < "$b" ))  
<= 小于等于   (( "$a" <= "$b" ))
> 大于     (( "$a" > "$b" ))
>= 大于等于   (( "$a" >= "$b" ))

比大小命令用法:

-eq 等于    if [ "$a" -eq "$b" ]
-ne 不等于1      if [ "$a" -ne 1 ]
-gt 大于2     if [ "$a" -gt 2 ]
-ge 大于等于3     if [ "$a" -ge 3 ]
-lt 小于      if [ "$a" -lt "$b" ]
-le 小于等于   if [ "$a" -le "$b" ]

 

对比脚本:

#!/bin/sh
description=$(cat /tmp/abc.txt |grep 'SYSTEM-A:'|wc -l)
if [ ${description} -eq 0 ];then
	cat << EOF >> /tmp/abc.txt
#####################################
#  APPSYSTEM: 系统的名字是啥
#   SYSTEM-A: 系统管理员A角
#   SYSTEM-B: 系统管理员B角
#DESCRIPTION: 这台机器干啥的
#####################################
EOF
elif [ $description -eq 1 ];then
	echo "文件中存在冲突配置,请手动检查,不可以自动修改"
else 
	echo "重复配置了${description}次"
fi

判断是否 为“空”还是 为“0”

if [ -z "$work" ] if [ "$work" -eq 0 ]的区别

if [ -z "$work" ]检查变量是否为空字符串。

if [ "$work" -eq 0 ] 检查变量是否等于数字 0。 

if [ -z "$work" ] 和 if [ "$work" -eq 0 ] 是两种不同的条件判断语句,用于检查变量的值是否满足特定条件。

if [ -z "$work" ]:
这个条件判断语句用于检查变量 "$work" 是否为空。如果变量值为空字符串,也就是没有内容,那么条件成立,if 语句块内的代码将被执行。

if [ "$work" -eq 0 ]:
这个条件判断语句用于检查变量 "$work" 是否等于数字 0。如果变量值等于 0,那么条件成立,if 语句块内的代码将被执行。

这两种条件判断的区别在于对变量内容的检查方式不同,第一种检查空字符串,第二种检查数值。你应该根据你的具体需求选择适合的条件判断方式。 

 


单引号、双引号、飘号的用法:为了防止空格、tab、等号等符号将字段隔开,我们将使用括号将他们视为一个整体

飘号 ` ` :执行内的命令

单引号 ' '单引号所括内容将被视为一字符串(请加深理解),像$等字符不会被执行。

双引号 " "双引号所括内容将被视为一字符串(请加深理解),它防止通配符扩展,但允许变量扩展,即像$符这种指令是会执行的。

如果不想执行可在$前加上转义字符 \,或改为单引号。 (就像sqoop指令中SQL语句后的$conditions 前就必须加转义字符,否则会在双引号内被提前解析)

举例脚本

#!/bin/bash
do_date=$1
echo '$do_date'    #单引号--所见即所得
echo "$do_date"    #双引号--翻译内部
echo "'$do_date'"  #双引号套用单引号
echo '"$do_date"'  #单引号套用双引号
echo `date`        #飘号--执行飘号内的命令

运行结果为

root@zys-t02:/root# bash test.sh 2020-06-14
$do_date        #单引号--所见即所得
2020-06-14      #双引号--翻译内部
'2020-06-14'    #双引号套用单引号
"$do_date"      #单引号套用双引号
2023年 01月 10日 星期四 16:02:08 CST    #飘号--执行飘号内的命令

总结单双和反引号用法:

(1)单'引号'不取变量值,直接输出

sed -i ${Num_TMOUT}'c #export TMOUT参数已注释' /etc/profile

(2)双"引号"取变量值后输出

sed -i ${Num_TMOUT}"c \#export TMOUT参数已注释" /etc/profile

(3)`飘号`执行飘号中命令

(4)外双引号+内单引号,取出变量值

特殊情况:使用额外的单引号对冲来解决 

取行号脚本

#!/bin/bash
Repair_TMOUT=`cat /etc/profile | grep "^export TMOUT" | head -n1`
#head -n1前1行,tail -n2后2行
if [ "$Repair_TMOUT" ];then
#标准用法是
LIN_NUM=$(sed -n '/匹配内容/=' /etc/profile)
方法一#使用变量时用外单引号+内双引号解决
LIN_NUM=$(sed -n '/'"$Repair_TMOUT"'/=' /etc/profile)
方法二#还是用双引号简单
LIN_NUM=$(sed -n "/${Repair_TMOUT}/=" /etc/profile)

方法三#一条命令
sed -n "/^export TMOUT/=" /etc/profile
方法四#一条命令
cat /etc/profile |grep -n ^"export TMOUT"|awk -F[:] '{print $1}'

(5)外单引号+内双引号,不取出变量值永远直接输出

举例:

echo $(date)    #执行date命令--取值--输出
echo `date`     #飘号是执行内容,类似于上面的$(XXX)。这里`data`==$(date)

这两条的运行结果都是:

2020年 06月 18日 星期四 21:02:08 CST

运行

echo date

结果为:

 


特殊符号意义

head -n1

tail -n1

awk 'NR==3 {print}' file.txt

#查询最后一行
awk 'END {print}' file.txt
sed -n '$p' file.txt
tail -n 1 file.txt

#查询第一行
awk 'NR==1 {print}' file.txt
sed -n '1p' file.txt
head -n 1 file.txt

 


sed -i  插入|替换|删除

插入

标准格式:2种写法结果都一样,但推荐将引号放在行号后面,因为出现变量时好处理
sed -i 1'i abc 123 xyz' /tmp/test.txt #在第1行之前插入abc 123 xyz
sed -i '1i abc 123 xyz' /tmp/test.txt #在第1行之前插入abc 123 xyz
演变格式1: i前、a后、c替换
sed -i 1'i abc 123 xyz' /tmp/test.txt #在第1行之前插入abc 123 xyz
sed -i 2'a efg' /tmp/test.txt  #在第2行之后插入efg
sed -i 3'c xyz wd 555' /tmp/test.txt  #把第3行数据替换成xyz wd 555
演变格式2:使用函数,注意双引号" "和单引号' '的区别
INT=66
sed -i 3'c $INT 123 xyz' /tmp/test.txt  #把第3行数据替换成$char 123 xyz
sed -i 3"c $INT 123 xyz" /tmp/test.txt  #把第3行数据替换成666 123 xyz
sed -i $INT"c $INT 123 xyz" /tmp/test.txt  #把第66行数据替换成66 123 xyz
sed -i $INT'c $INT 123 xyz' /tmp/test.txt  #把第66行数据替换成$INT 123 xyz

此时如果把单引号或者双引号放在外面就比较麻烦

双引号这种格式想解决就要严格要求里面的各种格式

甚至需要用外单引号对冲来解决问题,非常不建议使用

替换

几种写法:#把第1行数据替换成abc 123 haha 推荐使用双引号格式,参考双引号和单引号的区别
sed -i 1"c abc 123 haha" /tmp/abc.txt#最推荐格式
sed -i 1'c abc 123 haha' /tmp/abc.txt
sed -i "1c abc 123 haha" /tmp/abc.txt
sed -i '1c abc 123 haha' /tmp/abc.txt

变种举例:
Num=6
sed -i 1'c abc 123 haha' /tmp/abc.txt  把第1行数据替换成abc 123 haha
sed -i 2'c ${Num} 123 haha' /tmp/abc.txt  把第2行数据替换成${Num} wd 555 不转译
sed -i 3"c ${Num} 123 haha" /tmp/abc.txt  把第3行数据替换成(Num变量的值)6 123 haha 转译
sed -i ${Num}"c abc ${Num} haha" /tmp/abc.txt  把第(Num变量值)的行数,据替换成 abc 6 haha#最推荐格式

sed -i 's 新字符串 替换 原字符串

双引号和单引号均可以,参考双引号和单引号的区别
sed -i "s/原字符串/新字符串/" /home/1.txt    #每行只执行一次
sed -i "s/原字符串/新字符串/g" /home/1.txt   #每行执行多次

举例:
#cat 1.txt的内容如下
d
ddd
#ff

sed -i "s/d/7523/" /home/1.txt
执行结果
7523
7523dd
#ff

sed -i "s/d/7523/g" /home/1.txt
执行结果
7523
752375237523
#ff

替换第几行文字  "c

sed -i 1"c xyz wd 555" /tmp/abc.txt

sed -i ${line_num}"c MaxAuthTries    5" /etc/ssh/sshd_config

line_num=$(sed -n "/^MaxAuthTries/=" /etc/ssh/sshd_config)
#找出/etc/ssh/sshd_config路径下的【^MaxAuthTries】字段的行数,赋值给line_num
sed -i ${line_num}"c MaxAuthTries	5" /etc/ssh/sshd_config
#用这个line_num行数取值,替换掉这一行为【MaxAuthTries	5】

删除变量表示的行号  (可配合for等语句使用)

双引号和单引号均可以,参考双引号和单引号的区别
sed -i "${var1}d" /etc/abc.txt
#这里引号必须为双引号

删除第N~M行
sed -i 'N,Md' filename    #file的[N,M]行都被删除

sed -i "${var1},${var2}d" /etc/abc.txt
#这里引号必须为双引号

删除包含指定字符串的整行sed -i  ——/d(删除)

sed -i '/字符串/d' /etc/hosts

双引号和单引号均可以,参考双引号和单引号的区别
sed -i '/ntpserver/d' /etc/hosts
#删除/etc/hosts 里包含ntpserver的行

 


多层查询(以下两种方法结果相同)grep -v (非)

#查询/tmp/abc.txt文件 | 有【host name】| 不是以#开头的 | 计数

cat /tmp/abc.txt | grep 'host name'| grep -v ^#| wc -l

#查询/tmp/abc.txt文件 | 以【host name】开头的  | 计数

cat /tmp/abc.txt | grep ^'host name'| wc -l

 


for循环控制语句的3种用法

declare是bash的一个内建命令,可以用来声明shell变量、设置变量的属性。

declare也可以写作typeset。declare -i sum 代表强制把sum变量当做int型参数运算。

用法1:

for ((初始值;限制值;执行步阶))

do

程序段

done

初始值:变量在循环中的起始值

限制值:当变量值在这个限制范围内时,就继续进行循环

执行步阶:每作一次循环时,变量的变化量

#!/bin/bash
declare -i sum
sum=0
for ((i=0;$i<=10;i=$i+1))
do
    sum=$sum+$i
done
echo "sum=$sum"

用法2:for in + 固定范围内

for num in 1 2 3 4 5
do
    echo "$num"
done

 用法3:for in + 执行语句

#!/bin/bash
declare -i num LIN_NUM
timeout=$(cat ccc |grep "^TMOUT" |head -n1)
num=1
if [ "$timeout" ];then
  for q in `cat ccc |grep -n "^TMOUT="`
  do
      LIN_NUM=$(echo $q |awk -F':' '{print $1}')
      if [ $num == 1 ];then
          sed -i $LIN_NUM'c TMOUT=600' ccc
		  num=$num+1
		  echo $LIN_NUM
      else
          sed -i "${LIN_NUM}c \#TMOUT参数已替换" ccc
		  num=$num+1
		 echo $LIN_NUM
      fi
  done
fi
#仅修改第一个匹配到的目标,其余的目标替换为“#TMOUT参数已替换”

 

函数赋值:执行命令后赋值,需要使用$( )或者` `

Num=$(cat /etc/ssh/sshd_config | grep ^PasswordAuthentication |wc -l)
或者
Num=`cat /etc/ssh/sshd_config | grep ^PasswordAuthentication |wc -l`

 

posted @ 2023-01-09 16:36  Magiclala  阅读(200)  评论(0编辑  收藏  举报