shell编程实战学习(1)

shell编程实战学习(1)

一、shell介绍

1.1.1 什么shell

  1. Shell是一门解释性编程语言 Linux/Unix系统的底层以及基础软件的核心大部分都有涉及Shell脚本的内容,每一个合格的Linux系统管理员和运维工程师,都需要熟练Shell脚本语言的编写,并且能够阅读系统及各类软件Shell脚本内容。
  2. Shell编程是Linux运维人员常用的自动化编程语言,在工作合理的使用Shell编程脚本可以提高工作的效率,减少不必要的重复工作。

二、Shell实践

2.1.1 Shell的变量定义

  1. 查看系统默认的Shell类型
[root@web01 ~]# echo $SHELL
/bin/bash
[root@web01 ~]# grep  root /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@web01 ~]# bash --version
bash --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
  1. 什么的变量:用一个简单的字符串(或者字符数字)来替代更多更复杂的内容
  2. Linux变量的类型

1)局部变量(普通变量):编写shell脚本最常用的,变量名是以字母开头加数字或下划线组成的。

[root@node ~]# a=root
[root@node ~]# echo $a
root

[root@node ~]# a=1
[root@node ~]# b=2
[root@node ~]# echo $((a + b))
3

[root@node ~]# A="i am chj"
[root@node ~]# B=" I in studying linux"
[root@node ~]# echo $A$B
i am chj I in studying linux

[root@web01 ~]# x=1
[root@web01  ~]# echo $x
1
[root@web01  ~]# echo $xb

[root@web01 ~]# echo ${x}b
1b

2)全局变量(环境变量):在整个系统中生效、一般为大写字母、是系统中默认就存在的变量,这样的变量是满足系统和程序程序运行的需求。

[root@web01 ~]# echo $PATH
echo $PATH
/application/mysql/bin:/application/nginx/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin:/root/bin
[root@web01 ~]# echo $HOME
echo $HOME
/root
[root@web01 ~]# echo $UID
echo $UID
0
#自定义环境变量 可以添加到/etc/profile
[root@web01 ~]# export LINUX=1
[root@web01 ~]# echo $LINUX
1
  1. 在Linux系统中 ''单引号 ""双引号 不加引号的区别

1)单引号'' 所见即所得 [root@web01 ~]# echo '$HOME' $HOME
2)双引号" " 会将内容解析一下 [root@web01 ~]# echo "$HOME" 不加引号 和“”号功能相同

  1. shell变量名的定义:

一般字母,数字,下划线组成,以字母开头.不能以数字和特殊字符串开头
'你好?' 内容不会被解析 输出为纯字符串 .原模原样他输出
"你好?" 如果被赋值给其他变量 不会输出字符串 而是输出变量值 就是说会把变量解析了在输出
编程好习惯:数字可以不加双""号 ,其它都要默认加上

  1. Shell特殊重要变量
位置变量 作用说明
$0 获取当前执行Shell脚本文件名,如果执行脚本带路劲,那就包括脚本路径
$n 获取当前执行的Shelll脚本的n个参数值,n=1..9,当n为0时表示脚本的文件名,如果n大于9,例如:${10},接的参数咦空格隔开
$# 获取当前执行的Shell脚本后面接的参数的总个数
$* 获取当前Shell脚本所有传参参数,不加引号作用同$@;如果给$加上双引号,例如:“$”,则表示将所有的参数视为单个字符串,相当于“$1 $2 $3”
$@ 获取当前Shell脚本所有传参参数,不加引号作用同$,如果给$@加上双引号,例如:$@,则表示将所有的参数视为不同的独立字符串,相当于 "$1" "$2" "$3" "...", 这是将多参数传递给其他程序的最佳方式,因为他会保留所有内嵌在每个参数里的任何空白。当“$@”和“$” 都加双引号时,二者有区别,都不加双引号时,二者无区别
$? 检测执行脚本或命令的返回值是否为0(成功) 不为0(失败)
$$ 获取当前执行脚本的进程号
$! 获取上一个在后台执行的脚本进程号,了解即可
$_ 获取在此前执行命令或脚本的最后一个参数,了解即可
$0
[root@web01 /server/scripts]# cat arg.sh
#!/bin/bash
echo $0
[root@web01 /server/scripts]# sh arg.sh
arg.sh
[root@web01 /server/scripts]# sh /server/scripts/arg.sh 
/server/scripts/arg.sh
$n
[root@web01 /server/scripts]# cat arg.sh 
#!/bin/bash
echo $0
echo $1 $2 
[root@web01 /server/scripts]# sh arg.sh a b 
arg.sh
a b
#不加花括号
[root@web01 /server/scripts]# cat arg.sh 
#!/bin/bash
echo $0
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
[root@web01 /server/scripts]# sh arg.sh {a..z}
arg.sh
a b c d e f g h i a0 a1 a2 a3 a4 a5
#加花括号
[root@web01 /server/scripts]# cat arg.sh 
#!/bin/bash
echo $0
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
[root@web01 /server/scripts]# sh arg.sh {a..z}
arg.sh
a b c d e f g h i j k l m n o
$#
[root@web01 /server/scripts]# cat arg.sh 
#!/bin/bash
echo $0
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
echo $#
[root@web01 /server/scripts]# sh arg.sh {a..z} 
arg.sh
a b c d e f g h i j k l m n o
26
[root@web01 /server/scripts]# sh arg.sh a b 
arg.sh
a b
2
$*和$@
#不加双引号时
[root@web01 /server/scripts]# for i in $@;do echo $i;done
I
am
linux
study.
[root@web01 /server/scripts]# for i in $*;do echo $i;done
I
am
linux
study.
#都是三个字符串

#加双引号时
[root@web01 /server/scripts]# set -- "I am" linux study.
[root@web01 /server/scripts]# for i in "$*";do echo $i;done
I am linux study.  #代表一个字符串
[root@web01 /server/scripts]# for i in "$@";do echo $i;done
I am
linux
study.  #代表三个字符串
$?
#不为0时
[root@web01 /server/scripts]# nkir
-bash: nkir: command not found
[root@web01 /server/scripts]# echo  $?
127
#为0时
[root@web01 /server/scripts]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:ae:f7:fe brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.7/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feae:f7fe/64 scope link 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:ae:f7:08 brd ff:ff:ff:ff:ff:ff
    inet 172.16.1.7/16 brd 172.16.255.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feae:f708/64 scope link 
       valid_lft forever preferred_lft forever
[root@web01 /server/scripts]# echo  $?
0
$$
[root@web01 /server/scripts]# cat arg.sh 
#!/bin/bash
echo $*
echo $@
echo $$  #脚本中可以这样写 echo $$|tee /tmp/sh.pid 不但输出到屏幕上而且输出到sh.pid里
[root@web01 /server/scripts]# sh arg.sh 1 3
1 3
1 3
3165        #这就是进程号
#扩展tee命令介绍
Linux tee命令用于读取标准输入的数据,并将其内容输出成文件。
tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。
    -a或--append  附加到既有文件的后面,而非覆盖它.
    -i或--ignore-interrupts  忽略中断信号。
    --help  在线帮助。
    --version  显示版本信息。
[root@web01 /server/scripts]# echo "linux"|tee /tmp/linux.log
linux
[root@web01 /server/scripts]# cat /tmp/linux.log 
linux
  1. Shell 变量子串的应用
表达式 说明
${parameter} 返回变量$parameter的内容
${#parameter} 返回变量$parameter内容的长度(按字符),也适用于特殊变量
${parameter:offset} 在变量${parameter}中,从位置offset之后开始提取子串到结尾
${parameter:offset:length} 在变量${parameter}中,从位置offset之后开始提取长度为length的子串
${parameter#word} 从变量${parameter}开头开始删除最短匹配的word子串
${parameter##word} 从变量${parameter}开头开始删除最长匹配的word子串
${parameter%word} 从变量${parameter}结尾开始删除最短匹配的word子串
${parameter%%word} 从变量${parameter}结尾开始删除最长匹配的word子串
${parameter/pattern/string} 使用string代替第一个匹配的pattern
${parameter//pattern/string} 使用string代替所有匹配的pattern
#打印内容
[root@web01 /server/scripts]# OLDBOY="I am oldboy"
[root@web01 /server/scripts]# echo ${OLDBOY}
I am oldboy
#打印字符长度
[root@web01 /server/scripts]# OLDBOY="I am oldboy"
[root@web01 /server/scripts]# echo ${#OLDBOY}
11
#截取内容
[root@web01 /server/scripts]# OLDBOY="I am oldboy"
[root@web01 /server/scripts]# echo ${OLDBOY}
I am oldboy
[root@web01 /server/scripts]# echo ${OLDBOY:2:2}
am
[root@web01 /server/scripts]# echo ${OLDBOY:2}
am oldboy
#删除
#(从开头删)
{parameter#word}	从变量${parameter}【开头】开始删除最【短】匹配的word子串
[root@web01 /server/scripts]# OLDBOY=abcABC123ABCabc
[root@web01 /server/scripts]# echo $OLDBOY
abcABC123ABCabc
[root@web01 /server/scripts]# echo ${OLDBOY#a*C}
123ABCabc
{parameter##word}	从变量${parameter}【开头】开始删除最【长】匹配的word子串
[root@web01 /server/scripts]# OLDBOY=abcABC123ABCabc
[root@web01 /server/scripts]# echo $OLDBOY
abcABC123ABCabc
[root@web01 /server/scripts]# echo ${OLDBOY##a*C}
abc
#(从结尾删)
{parameter%word}	从变量${parameter}结尾开始删除最短匹配的word子串
[root@web01 /server/scripts]# OLDBOY=abcABC123ABCabc
[root@web01 /server/scripts]# echo ${OLDBOY%a*c}
abcABC123ABC
{parameter%%word}	从变量${parameter}结尾开始删除最长匹配的word子串
[root@web01 /server/scripts]# OLDBOY=abcABC123ABCabc
[root@web01 /server/scripts]# echo ${OLDBOY%%A*c}
abc
#单个匹配替换
[root@web01 /server/scripts]# OLDBOY="I am oldboy ,yes oldboy"
[root@web01 /server/scripts]# echo ${OLDBOY}
I am oldboy ,yes oldboy
[root@web01 /server/scripts]# echo ${OLDBOY/oldboy/oldgirl}
I am oldgirl ,yes oldboy
#全部匹配替换
[root@web01 /server/scripts]# OLDBOY="I am oldboy ,yes oldboy"
[root@web01 /server/scripts]# echo ${OLDBOY}
I am oldboy ,yes oldboy
[root@web01 /server/scripts]# echo ${OLDBOY//oldboy/oldgirl}
I am oldgirl ,yes oldgirl

8.面试题

#利用shell脚本打印出字符照度小于6的单词 I am oldboy linux welcome to our training.
[root@web01 /server/scripts]# cat count.sh 
chars="I am oldboy linux welcome to our training."

for i in $chars
do 
  if [ ${#i} -lt 6 ]
   then
   echo $i
fi
done
[root@web01 /server/scripts]# sh count.sh
I
am
linux
to
our
[root@web01 /server/scripts]# test=lele
[root@web01 /server/scripts]# echo $test
lele
[root@web01 /server/scripts]# result=${test:-unset}
[root@web01 /server/scripts]# echo $result
lele
[root@web01 /server/scripts]# unset test
[root@web01 /server/scripts]# echo $test

[root@web01 /server/scripts]# result=${test:-unset}
[root@web01 /server/scripts]# echo $result
unset
#实例删除脚本
[root@web01 /server/scripts]# cat del.sh 
#!/bin/bash
DIR=/opt/

find ${DIR:-/tmp/} -name "*.tar.gz" -type f -mtime +7 |xargs rm -fr
rm -rf ${DIR:-/tmp/}   
[root@web01 /server/scripts]# ll /opt
ls: cannot access /opt: No such file or directory
[root@web01 /server/scripts]# cat del.sh 
#!/bin/bash
#DIR=/opt/      #如果将DIR变量注释掉,就会删除tmp目录
find ${DIR:-/tmp/} -name "*.tar.gz" -type f -mtime +7 |xargs rm -fr
rm -rf ${DIR:-/tmp}
[root@web01 /server/scripts]# sh -x del.sh 
+ xargs rm -fr
+ find /tmp/ -name '*.tar.gz' -type f -mtime +7
+ rm -rf /tmp

2.1.2 变量数值计算

  1. 计算符号
计算符号 意义
+ 、- 加 减
*、/ 、% 乘法 除法 取模
** 幂运算
++、-- 增加及减少,可前置也可放在变量结尾,默认步长为1
!、&&、|| 逻辑非(取反)、逻辑与(and)、逻辑或(or)
<、<=、>、>= 比较符号 (小于、小于等于、大于、大于等于)
==、!=、= 比较符号 (相等 、不等于、对于字符串“=”也可以表示相当)
<< 、>> 向左移位、向右移位
~、|、&、^ 按为取反、按位异或、按位与、按位或
=、+=、-=、*=、/=、%= 赋值运算符,列如a+=1相当于a=a+1,a-=1相当于a=a-1
  1. Shell 的常见算术运算命令
运算操作符与命令 作用
(()) 用于整数运算的常用运算符,效率很高
let 用于整数运算,类似(())
expr 可用于整数运算,但还有很多其它的额外功能
bc Linux下的一个计算器程序(适合整数以及小数运算)
$[] 用于整数运算
awk awk 即可用于整数运算,也可以用于小数运算
declare 定义变量数值和属性,-i参数可以用于定义整形变量,做运算
  1. 运算实战
#(())
[root@web01 /server/scripts]# ((a=1+10))
[root@web01 /server/scripts]# echo $a
11
#let
[root@web01 /server/scripts]# a=1
[root@web01 /server/scripts]# let a=a+1
[root@web01 /server/scripts]# echo $a
2
#expr
[root@web01 /server/scripts]# expr 2 + 3
5
[root@web01 /server/scripts]# expr 2 - 3
-1
[root@web01 /server/scripts]# expr 2 / 3
0
#bc
[root@web01 /server/scripts]# echo 1 + 3 |bc
4
[root@web01 /server/scripts]# echo 3-2 |bc
1
[root@web01 /server/scripts]# echo 3 - 2 |bc
1
[root@web01 /server/scripts]# echo 3 / 2 |bc
1
[root@web01 /server/scripts]# echo 1.2 + 1.8 |bc
3.0
#$[]
[root@web01 /server/scripts]# echo $[20+30]
50
[root@web01 /server/scripts]# echo $[20/30]
0
[root@web01 /server/scripts]# echo $[20*30]
600
#awk
[root@web01 /server/scripts]# echo 5 6|awk '{print $1*$2}'
30
[root@web01 /server/scripts]# echo 5.2 6|awk '{print $1*$2}'
31.2
[root@web01 /server/scripts]# echo 2 6|awk '{print $1**$2}'
64
[root@web01 /server/scripts]# echo 5 6|awk '{print $1-$2}'
-1
[root@web01 /server/scripts]# echo 6 5|awk '{print $1/$2}'
1.2
[root@web01 /server/scripts]# echo 6 5|awk '{print $1%$2}'
1
#declare
[root@web01 /server/scripts]# declare -i a=10+30
[root@web01 /server/scripts]# echo $a
40
[root@web01 /server/scripts]# declare -i a=10*30
[root@web01 /server/scripts]# echo $a
300

2.1.3 expr的功能

  1. 计算
[root@web01 /server/scripts]# expr 1 + 3
4
  1. 获取字符串长度功能
[root@web01 /server/scripts]# expr length "linux"
5
  1. 判断字符串是否为数字或字符
[root@web01 /server/scripts]# a=1
[root@web01 /server/scripts]# expr $a + k &>/dev/null
[root@web01 /server/scripts]# echo $?
2
[root@web01 /server/scripts]# expr $a + 1 &>/dev/null
[root@web01 /server/scripts]# echo $?
0
  1. 用来判断文件扩展名是否符合指定扩展名
[root@web01 /server/scripts]# cat jubeo.sh 
#!/bin/bash
if expr "$1" : ".*.avi$" >/dev/null ; then
   echo "好兴奋啊"
else
    echo "好失望啊"
fi
[root@web01 /server/scripts]# sh jubeo.sh linx.avi
好兴奋啊
[root@web01 /server/scripts]# sh jubeo.sh linx.loj
好失望啊
原文地址:https://www.cnblogs.com/woaiyunwei/p/12942094.html