为什么学习shell编程

shell脚本语言是实现linux/unix 系统管理机自动化运维所必备的重要工具,linux/unix系统的底层及基础应用软件的核心大部分涉及shell脚本的内容。每一个合格的linux系统管理员或运维工程师,都需要熟练的编写shell脚本语言,并能够阅读系统及各类软件附带的shell脚本内容


什么是shell

shell是一个命令解释器,它在操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕返回给用户,这种对话方式可以是交互式(从键盘输入命令,可以立即得到shell的回应),或非交互(执行脚本程序)的方式

shell种类

交互式shell
非交互式shell
登录式shell

/etc/profile -> /etc/profile.d/*.sh -> ~/.bash_profile -> ~/.bashrc -> /etc/bashrc

非登录式shell

~/.bashrc -> /etc/bashrc

shell执行方式

1、 bash script-name 或 sh script-name (生成一个子shell执行)

2、 path/script-name 或 ./script-name (添加执行权限执行,默认根据脚本第一行指定的解释器执行,如果没有指定则以当前默认shell解释器执行)

3、 source script-name 或 . script-name (以当前默认shell解释器执行)

4、cat script-name |bash

子shell

子shell的本质是shell的子进程

子进程是由父进程的概念引申而来,在linux系统下,我们所运行的应用程序几乎都是从init(systemd)(pid为1的进程)进程延伸出来的,所以这些应用程序都视为init进程的子进程,而init则为它们的父进程

shell子进程是从一个父shell进程调用shell程序而产生的一个全新的shell,我们将这种全新的shell统称为这个父shell的子shell

产生子shell的情况

1、在父shell中执行一个shell脚本
bash ,执行环境不同,不能直接引用父shell变量,需export,定义的变量不能被父shell引用

2、在父shell中执行一条命令,在命令的末尾加上&
&,执行环境相同,直接引用父shell变量,定义的变量不能被父shell引用
STR0='123';STR0='abc' &
echo $STR0

3、在父shell中执行一条命令,使用 () 中执行
(),执行环境相同,直接引用父shell变量,定义的变量不能被父shell引用
[root@web01 shell_class_03]# STR2='123' && (STR2='abc') && echo $STR2
123

4、在父shell中执行带管道的命令
管道,执行环境相同,直接引用父shell变量,定义的变量不能被父shell引用
[root@web01 shell_class_03]# STR1='123';echo 111 |STR1='ABC';echo $STR1
123


shell应用场景

  • 系统基础配置
  • 部署应用服务
  • 配置应用服务
  • 部署业务代码
  • 应用服务备份
  • 日志分析
  • 监控应用服务

shell基础

  • 命令补全和文件路径补全, 如果写错无法补全 table
  • 命令历史记忆功能 history
  • 别名功能 alias、unalias
  • 常用快捷键 ctrl+u,k,a,e,l,c,z,d,r
  • 前后台作业控制 bg,fg,jobs,screen
  • 输入输出重定向 > >> 2> 2>> < << &> cat
  • | 将前者命令的标准输出交给后者命令的输入
  • |& 将前者命令的错误输出交给后者命令的输入
  • 命令之间的关系; 没有逻辑关系,无论分号前面的命令执行是否成功都执行后者命令&& 前面执行成功, 则执行后者|| 前面执行不成功, 则执行后者

shell通配符

  • 匹配任意多个字符

? 匹配任意一个字符
[] 匹配括号中任意一个字符a-z,0-9,A-Z,a-Z
() 在子 shell 中执行(cd /boot;ls) (umask 077; touch file1000)
{} 集合 touch file{1..9}

\ 转义符

shell模式匹配
使用shopt 内置命令启用shell选项 (extglob) 则会识别几个扩展模式匹配运算符。
模式列表是由 | 分割

查看shell选项 extglob

shopt |grep extglob

启动shell选项 extglob

shopt -s extglob

关闭shell选项 extglob

shopt -u extglob
** 模式 ** ** 说明 **
?(pattern-list) 匹配给定模式零或一次
*(pattern-list) 匹配给定模式零次或多次
+(pattern-list) 匹配给定模式一次或多次
@(pattern-list) 匹配给定模式之一
!(pattern-list) 匹配除了给定的模式
[root@mycentos6-clone ~]# ll
total 0
-rw-r--r-- 1 root root 0 Nov 1 07:02 123
-rw-r--r-- 1 root root 0 Nov 1 07:02 aaaac
-rw-r--r-- 1 root root 0 Nov 1 06:51 aaab
-rw-r--r-- 1 root root 0 Nov 1 07:02 aad
-rw-r--r-- 1 root root 0 Nov 1 07:02 aadg
-rw-r--r-- 1 root root 0 Nov 1 07:02 bb
-rw-r--r-- 1 root root 0 Nov 1 07:02 c
[root@mycentos6-clone ~]# ls !(c|bb|123)
aaaac aaab aad aadg
[root@mycentos6-clone ~]# rm !(c|bb|123) -f
[root@mycentos6-clone ~]# ll
total 0
-rw-r--r-- 1 root root 0 Nov 1 07:02 123
-rw-r--r-- 1 root root 0 Nov 1 07:02 bb
-rw-r--r-- 1 root root 0 Nov 1 07:02 c

单引号-双引号-没有引号

引号和不加引号的区别1

[root@zeqtx ~]# touch a b
[root@zeqtx ~]# ll
total 0
-rw-r--r--. 1 root root 0 Jun 25 16:25 a
-rw-r--r--. 1 root root 0 Jun 25 16:25 b
[root@zeqtx ~]# touch "a b"
[root@zeqtx ~]# ll
total 0
-rw-r--r--. 1 root root 0 Jun 25 16:25 a
-rw-r--r--. 1 root root 0 Jun 25 16:25 a b
-rw-r--r--. 1 root root 0 Jun 25 16:25 b

引号和不加引号的区别2:

[root@zeq36 tmp]# ll
总用量 0
-rw-r--r-- 1 root root 0 6月 25 19:36 ?
-rw-r--r-- 1 root root 0 6月 25 19:32 *
-rw-r--r-- 1 root root 0 6月 25 19:33 aa
-rw-r--r-- 1 root root 0 6月 25 19:33 abc
-rw-r--r-- 1 root root 0 6月 25 19:33 b
[root@zeq36 tmp]# ll ?
-rw-r--r-- 1 root root 0 6月 25 19:36 ?
-rw-r--r-- 1 root root 0 6月 25 19:32 *
-rw-r--r-- 1 root root 0 6月 25 19:33 b
[root@zeq36 tmp]# ll "?"
-rw-r--r-- 1 root root 0 6月 25 19:36 ?
[root@zeq36 tmp]# ll *
-rw-r--r-- 1 root root 0 6月 25 19:36 ?
-rw-r--r-- 1 root root 0 6月 25 19:32 *
-rw-r--r-- 1 root root 0 6月 25 19:33 aa
-rw-r--r-- 1 root root 0 6月 25 19:33 abc
-rw-r--r-- 1 root root 0 6月 25 19:33 b
[root@zeq36 tmp]# ll "*"
-rw-r--r-- 1 root root 0 6月 25 19:32 *

双引号和单引号区别1:

关于$

[root@zeqtx ~]# echo "$LANG"
en_US.UTF-8
[root@zeqtx ~]# echo '$LANG'
$LANG

双引号和单引号区别2:

关于``

[root@zeqtx ~]# echo "`which awk`"
/bin/awk
[root@zeqtx ~]# echo '`which awk`'
`which awk`

双引号和单引号区别3:

关于!

[root@zeqtx ~]# echo '!ll'
!ll
[root@zeqtx ~]# echo "!ll"
echo "ll /bin/awk "
ll /bin/awk

shell常用命令与工具

cat

cat<<-EOF
1.[install lamp]
2.[install lnmp]
3.[exit]
EOF
cat >> /etc/profile <<'EOF'
$PATH
EOF

read

格式:

read [options] varible1 varible2 ...

参数:

-p 显示提示信息
-t 超时时间
-s 取消回显
-u 绑定文件描述符作为输入
-a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符

eval

  • 执行参数做为shell命令
[root@VM_153_209_centos ~]# echo $a
3
[root@VM_153_209_centos ~]# echo $b
stu
[root@VM_153_209_centos ~]# eval echo ${b}{1..$a}
stu1 stu2 stu3

tee

  • 从标准输入读取写到出和文件
  • -a 追加到文件

printf

a=1
b=3
printf "%.2f" `echo "scale=2;$a/$b"|bc`

:

空命令

echo

字体颜色

echo -e "\033[30m 黑色字zeq trainning \033[0m"
echo -e "\033[31m 红色字zeq trainning \033[0m"
echo -e "\033[32m 绿色字zeq trainning \033[0m"
echo -e "\033[33m 黄色字zeq trainning \033[0m"
echo -e "\033[34m 蓝色字zeq trainning \033[0m"
echo -e "\033[35m 紫色字zeq trainning \033[0m"
echo -e "\033[36m 天蓝字zeq trainning \033[0m"
echo -e "\033[37m 白色字zeq trainning \033[0m"

背景颜色

echo -e "\033[40;37m 黑底白字 welcome to ze1q\033[0m"
echo -e "\033[41;37m 红底白字 welcome to ze2q\033[0m"
echo -e "\033[42;37m 绿底白字 welcome to ze3q\033[0m"
echo -e "\033[43;37m 黄底白字 welcome to ze4q\033[0m"
echo -e "\033[44;37m 蓝底白字 welcome to ze5q\033[0m"
echo -e "\033[45;37m 紫底白字 welcome to ze6q\033[0m"
echo -e "\033[46;37m 天蓝白字 welcome to ze7q\033[0m"
echo -e "\033[47;30m 白底黑字 welcome to ze8q\033[0m"

trap

trap [-lp] [ [参数] 信号 ...]

参数 : shell命令

信号

HUP(1) 挂起,通常因终端掉线或用户退出而引发
INT(2) 中断,通常因按下Ctrl+C组合键而引发
QUIT(3) 退出,通常因按下Ctrl+组合键而引发
ABRT(6) 中止,通常因某些严重的执行错误而引发
ALRM(14) 报警,通常用来处理超时
TERM(15) 终止,通常在系统关机时发送
SIGTSTP 停止进程 终端来的停止信号

trap ':' INT EXIT TSTP TERM HUP

jumpserver.sh

#!/bin/bash
LB02=10.0.0.6
WEB01=10.0.0.7 menu(){
cat << EOF
1) LB02
2) WEB01
6) h
EOF
} while true
do
trap ':' INT TSTP TERM HUP
menu
read -p "please input hostname num: " NUM
case $NUM in
1|LB02)
ssh root@$LB02
;;
2|WEB01)
ssh root@$WEB01
;;
h)
menu
;;
exec)
exit 1
;;
esac
done

expect

#!/usr/bin/expect
set ip 10.0.0.6
set user root
set password 123456
set timeout 5 spawn ssh $user@$ip expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$password\r" };
}
#交互方式
interact

expect-copy-sshkey.exp

#!/usr/bin/expect
if { $argc != 1 } {
send_user "usage: expect expect-copy-sshkey.exp host \n"
exit
} #define var
set host [lindex $argv 0]
set password "123456" spawn ssh-copy-id -i /home/oldgirl/.ssh/id_dsa.pub "oldgirl@$host"
#spawn ssh -p 50718 disdata@$host /sbin/ifconfig
set timeout 60
expect {
-timeout 20
"yes/no" { send "yes\r";exp_continue }
"*password" { send "$password\r" }
timeout { puts "expect connect timeout,pls contact zeq."; return }
}
expect eof exit -onexit {
send_user "zeq say good bye to you!\n"
}

cat dis-sshkey.sh

#!/bin/sh
. /etc/init.d/functions
[ ! -f iplist ] && echo "hostlists.txt is not exist." && exit 1 for host in `cat /home/oldgirl/iplist`
do
expect expect-copy-sshkey.exp $host &>/dev/null
if [ $? -eq 0 ];then
action "$host dis data" /bin/true
else
action "$host dis data" /bin/false
fi
done

mkpasswd openssl

mkpasswd -l 10 -c 3 -C 3 -d 3
openssl rand -base64 80

basename dirname

basename /etc/init.d/network
network dirname /etc/init.d/network

/etc/init.d


shell脚本

脚本第一行

指定脚本解释器

#!/bin/sh
#!/bin/bash
#! /usr/bin/awk
#! /bin/sed
#! /usr/bin/tclsh
#! /usr/bin/expect
#! /usr/bin/perl
#! /usr/bin/env python

脚本注释

单行注释 #
多行注释

<<'EOF'
语句1
语句2
...
语句n
EOF

脚本构成

主脚本
模块(子脚本)

  • 主脚本 调用模块
  • 模块中 有 函数
  • 先调用模块,再调用函数

脚本执行参数

  • -x 将执行的脚本内容及输出显示到屏幕上
  • -n 不会执行该脚本,仅查询脚本语法是否有问题,并给出错误提示。
  • -v 在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也会给出错误提示

变量

变量类型

自定义变量

1.定义变量变量名=变量值 ,不允许数字命名, 不能使用横岗命名
2.引用变量$变量名 或 ${变量名}
3.查看变量echo $变量名 set显示所有变量,包括自定义变量和环境变量

4.取消变量unset 变量名 作用范围:仅在当前 shell 中有效

系统环境变量
1.定义环境变量 export export 变量 ,将自定义变量转换成环境变量
2.引用环境变量 $变量名 或 ${变量名}
3.查看环境变量 echo $变量名 env |grep Name
4.取消环境变量 unset 变量名
5.作用范围在当前shell和子shell有效

位置参数变量

$1
$2
$3

${10}

预先定义变量
$0 脚本文件名
$* 所有的参数
$@ 所有的参数

set  "I am" handsome zeq
for i in "$*" ; do echo $i; done
for i in "$@" ; do echo $i; done

$# 参数的个数
$$ 当前进程的 PID
$! 上一个后台进程的 PID
$? 上一个命令的返回值 0 表示成功

$_ 在此之前执行的命令或脚本的最后一个参数

变量赋值方式

1.显式赋值(变量名=变量值)

2.read从键盘读入变量值

read -p "请输入数字:"
echo $REPLY

3.定义或引用变量时注意事项: " "弱引用 ' '强引用

4.``命令替换等价于$()反引号中的shell命令会被先执行

变量子串

变量长度

${#string}

从前往后删除变量内容

${string#substring} 从变量$string开头开始删除最短匹配$substring子串
${string##substring} 从变量$string开头开始删除最长匹配$substring子串

从后往前删除变量内容

${string%substring} 从变量$string结尾开始删除最短匹配$substring子串
${string%%substring} 从变量$string结尾开始删除最长匹配$substring子串

索引及切片

${string:position} 在$string中,从$position个开始提取子串(从0开始计数)
${string:position:length} 在$string中,从位置$position之后开始提取长度为$length的子串

变量内容替换

${parameter/pattern/string} 使用string代替第一个匹配的pattern
${parameter//pattern/string} 使用string代替所有的pattern
${parameter/#pattern/string} 从开头匹配string变量中的pattern, 用string替换匹配的pattern
${parameter/%pattern/string} 从结尾匹配string变量中的pattern, 用string替换匹配的pattern

变量替代

${value:-word} 如果变量名存在且非null,则返回变量的值。否则,返回word字符串 用途:如果变量未定义,则返回备用的值
${value:=word} 如果变量名存在且非null,则返回变量值。否则,设置这个变量值为word 并返回其值 用途:如果变量未定义,则设置变量为默认值,并返回默认值
${value:?"not defined"} 如果变量名存在且非null,则返回变量的值。否则显示变量名:message, 并退出当前的命令或者脚本 用途:用于捕捉由于变量未定义而导致的错误,并退出程序
${value:+word} 如果变量名存在且非null,则返回word。 否则返回null 用途:测试变量是否存在

变量作用域

环境变量

使用 export 定义,在当前shell及其子shell中生效

本地变量

仅在当前shell中生效

局部变量

使用 local 定义 ,仅在函数中生效


表达式

运算符

++ -- 自增 自减

  • ! ~ 正号 负号 逻辑取反 按位取反
    / % 乘 除 取余
    • 加 减
      < <= > >= 比较符号
      == != 等于 不等于
      << >> 左移 右移
      & | ^ 按位与 按位或 按位异或
      && || 逻辑与 逻辑或
      = += -= *= /= %= &= |= ^= <<= >>= 各种赋值运算符
      ** 幂运算

算术运算(整数)

** [] test ** ** (()) [[]] **
-eq == 或 =
-ne !=
-gt >
-ge >=
-lt <
-le <=

自增/自减
ping.sh

#!/bin/bash
IP=223.5.5.5
i=1
while((i<=4))
do
if ping $IP -c 1 &> /dev/null;then
echo "ping $IP is ok!"
else
echo "ping $IP is faild..."
fi
let i++
done

表达式符号

[ ]
[[ ]]
(( )) 仅用于整数

((1<2&&1>3))
((1<2||1>3))

算术运算-bc

https://www.gnu.org/software/bc/manual/html_mono/bc.html

# a=1.2
# b=3
# echo "$a<$b" |bc
1
# echo "$a>$b" |bc
0
# echo "$a+$b" |bc
4.2
# x=$(echo "$a+$b" |bc)
# echo $x
4.2
[root@VM_153_209_centos scripts]# a=9.8
[root@VM_153_209_centos scripts]# b=10.1
[root@VM_153_209_centos scripts]# echo "$a>$b" |bc
0
[root@VM_153_209_centos scripts]# echo "$a<$b" |bc
1
cat test.bc
#!/bin/bc
1+2
quit
bc -q test.bc
3
#!/bin/bc
array[1]=1
array[2]=2
array[1]+array[2]
quit
bc -q test.bc
3

逻辑运算

** [] test ** ** [[]] ** ** 说明 **
-a && and 与
-o || or 或
! ! not 非

字符串运算

-z "str" 若串长度为0则真,-z 可以理解为zero
-n "str" 若串长度不为0则真,-n可以理解为no zero
"str1" = "str2" 若串1等于串2则真,可以使用 "==" 代替 "="
"str1" != "str2" 若串1不等于串2则真
"str1" =~ "pattern" 字符串匹配成功则为真 [[ ]]

文件测试

[ -f 文件 ] 文件存在且为普通文件则真,条件表达式成立
[ -d 目录 ] 目录存在且为目录文件则真,条件表达式成立
[ -s 文件 ] 文件存在且文件大小不为0则真,条件表达式成立
[ -e 文件 ] 文件存在则真,只要有文件就行
[ -r 文件 ] 文件存在且可读则真,条件表达式成立
[ -w 文件 ] 文件存在且可写则真,条件表达式成立
[ -L 文件 ] 文件存在且为链接文件则真,条件表达式成立
[ f1 -nt f2 ] 文件f1比文件f2新则真,条件表达式成立
[ f1 -ot f2 ] 文件f1比文件f2旧则真,条件表达式成立

流程控制

顺序 选择 循环

条件表达式

  • 条件表达式的值只有真(非0 | 非空 | 条件成立 | $?为0(此条shell特有))、假(0 | 空 | 条件不成立 | $?不为0(此条shell特有))此规则适用于所有的计算机高级语言

算术运算
逻辑运算
Linux命令

选择(分支)

if

if 条件表达式;then
命令
fi
#/bin/bash
http="ss -lntup|grep nginx &> /dev/null"
if eval $http
then
echo 1
else
echo 0
fi

流程图

st=>start: Start
op=>operation: 命令1
cond=>condition: 条件表达式为真?
e=>end st->cond
cond(yes)->op->e
cond(no)->e

if else

if 条件表达式;then
命令1
else
命令2
fi
st=>start: Start
op=>operation: 命令1
op2=>operation: 命令2
cond=>condition: 条件表达式为真?
e=>end st->cond
cond(yes)->op->e
cond(no)->op2->e

if elif else

if 条件表达式;then
命令1
elif 条件表达式2;then
命令2
else
命令3
fi
st=>start: Start
op=>operation: 命令1
op2=>operation: 命令2
op3=>operation: 命令3
cond=>condition: 条件表达式为真?
cond2=>condition: 条件表达式2为真?
e=>end st->cond
cond(yes)->op->e
cond(no)->cond2
cond2(yes)->op2->e
cond2(no)->op3->e

case

case 模式名 in
模式1)
命令1
;;
模式2)
命令2
;;
模式3)
命令3
;;
*)
其它命令
esac
st=>start: Start
io=>inputoutput: 模式名
op=>operation: 命令1
op2=>operation: 命令2
op3=>operation: 命令3
op4=>operation: 其它命令
cond=>condition: 模式名==模式1 ?
cond2=>condition: 模式名==模式2 ?
cond3=>condition: 模式名==模式3 ?
e=>end st->io->cond
cond(yes)->op->e
cond(no)->cond2
cond2(yes)->op2->e
cond2(no)->cond3
cond3(yes)->op3->e
cond3(no)->op4->e

循环

for

for 变量名 in 取值列表
do
命令
done
for ((expr1;expr2;expr3))
do
命令
done

expr1 初值expr2 终值expr3 步长值

st=>start: Start
op=>operation: 命令
op1=>operation: expr1
op3=>operation: expr3
cond=>condition: expr2为真 ?
e=>end st->op1->cond
cond(yes)->op->op3->cond
cond(no)->e

IFS

#!/bin/bash
data='a,b,c,d'
IFS=,
for i in $data;do
echo $i
done

while

while 条件表达式
do
命令
done
st=>start: Start
op=>operation: 命令
cond=>condition: 条件表达式为真 ?
e=>end st->cond
cond(yes)->op->cond
cond(no)->e

把a.txt文件中的内容倒腾到b.txt文件中

cat a.txt
1
2
3
4
5
6
7
8
9
10

cat b.txt
10
9
8
7
6
5
4
3
2

1

#!/bin/bash
touch b.txt
while [ -n "$(cat a.txt)" ]
do
if [ -z "$(cat b.txt)" ];then
head -1 a.txt > b.txt
else
sed -i "1i `head -1 a.txt`" b.txt
fi
sed -i 1d a.txt done

while read

while read -p "请输入:"
do
if [[ $REPLY =~ ^[0-9]+$ ]];then
echo "输出:$((REPLY*=${REPLY}00))"
elif [[ "$REPLY" = "q" ]];then
break
fi
done

while读取文件三种方式

1、
cat ./a.txt | while read LINE
do
echo $LINE
done 2、
while read LINE
do
echo $LINE
done < ./a.txt 3、
exec < ./a.txt
while read LINE
do
echo $LINE
done

break

break n 表示跳出循环的层数

省略n 表示跳出整个循环

continue
continue n 退到第n层继续循环

省略n 表示跳出本次循环,继续下一次循环

select

#PS3=[$USER@$0]#
select VAR in var1 var2 quit
do
case $VAR in
var1)
echo 1
;;
var2)
echo 2
;;
quit)
break
;;
esac
done

函数

函数定义

function 函数名(){
命令
}

函数参数

$1
$2
$3
$#
$*

$@

函数调用

函数名 参数1 参数2 参数3

函数返回

  • 返回数字作为函数执行状态 返回给$? 取值范围 0-255 (使用 return)
  • 返回数字作为函数执行结果 (使用 echo)
  • 返回字符串,作为函数执行结果 (使用 echo)

系统函数库

系统函数库

/etc/init.d/functions

action函数

action "xxxxx" /bin/trueaction "xxxxx" /bin/false

功能函数库

# 脚本初始化
function scripts_init(){
prog=`basename $0 .sh`
LockFile=/var/lock/subsys/${prog}.lock # 使用锁文件
LogFile=/var/log/${prog}.log # 脚本记录日志
PidFile=/var/run/${prog}.pid # 记录进程号,可以管理脚本 [ -f $LockFile ] && echo "There $LockFile is exist!!" && exit 1 ||touch $LockFile
[ ! -f $LogFile ] && touch $LogFile
[ -f $PidFile ] && echo "There $PidFile is exist!!" && exit 2|| echo $$ > $PidFile
} # 记录日志
function writelog(){
Date=$(date "+%F_%T")
ShellName=`basename $0`
Info=$1
echo "$Date : ${ShellName} : ${Info}" >> ${LogFile}
} # 脚本退出扫尾
function closeout(){
[ -f $LockFile ] && rm -f $LockFile
[ -f $PidFile ]&& rm -f $PidFile
} # 判断输入是整数
function int_judge(){
fun_a=$1
expr $fun_a + 1 &>/dev/null
RETVAL=$?
return $RETVAL
} # 判断输入非空
function input_judge(){
RETVAL=0
fun_a=$1
[ ${#fun_a} -eq 0 ]&& RETVAL=1
return $RETVAL
}

数组

  • 数组名代表首地址

下标是从0开始的整数

普通数组(索引数组)

定义数组

array=(a b c)

获取所有元素

${array[*]}

获取元素下标

${!a[@]}

获取数组长度

${#array[*]}

获取一个元素的长度

${#name[0]}

获取第一个元素

${array[0]}

获取第二个元素

${array[1]}

获取多个元素

array=(1 2 3 4 5)
echo ${array[@]:1}
2 3 4 5 #array[@]:下标:截取元素个数
echo ${array[@]:1:3}
2 3 4

添加元素

array[3]=d

添加多个元素

array+=(e f g)

删除第一个元素

unset array[0]    # 删除会保留元素下标

删除数组

unset array

数组切片

${name[4]:0:7}

关联数组

关联数组的下标是字符串

定义关联数组

declare -A M

关联数组赋值

M=([a]=11 [b]=22)

获取关联数组元素

echo ${M[a]}
11

获取关联数组元素个数

echo ${#M[@]}
2

获取关联数组下标

echo ${!M[*]}
a b

获取关联数组所有元素

echo ${M[@]}
11 22

添加元素

M[c]=33

添加多个元素

M+=([d]=33 [e]=44)

综合题

找出一个网络中最大的空闲ip地址段

#!/bin/bash
SUB_NET="10.0.0."
for NUM in {1..254}
do
{
if ping -c 1 ${SUB_NET}${NUM} &> /dev/null;then
echo $NUM >> ip.txt
fi
}&
done
wait
sort -n ip.txt -o ip.txt
if [ $(tail -1 ip.txt) -ne 254 ];then
echo 254 >> ip.txt
fi
while read LINE
do
array+=($LINE)
done < ip.txt for ((i=0;i<${#array[*]}-1;i++))
do
DIFF=$((${array[$((i+1))]}-${array[$i]}))
echo -e "${SUB_NET}${array[$((i+1))]}\t${SUB_NET}${array[$i]}\t$DIFF" >> result.txt
done sort -rnk3 result.txt
rm *.txt -f
#!/bin/bash
SUB_NET="10.0.0."
for NUM in {1..254}
do
{
if ping -c 1 ${SUB_NET}${NUM} &> /dev/null;then
echo $NUM >> ip.txt
fi
}&
done
wait
sort -n ip.txt -o ip.txt
if [ $(tail -1 ip.txt) -ne 254 ];then
echo 254 >> ip.txt
fi
awk -v net=$SUB_NET '{if(NR==1){last=$1}if(NR>1){printf "%s%d\t%s%d\t%d\n",net,$1,net,last,$1-last;last=$1}}' ip.txt |sort -nrk 3
rm ip.txt -f

抓阄

#!/bin/bash
function rand(){
echo $((RANDOM%100+1))
}
> /tmp/user.txt
while true
do
clear
echo "抓阄获奖名单如下: "
sort -rnk2 /tmp/user.txt |head -3
read -p 'please input name: ' NAME
[ -z "$NAME" ] && continue
if [ "$NAME" = "q" ];then
break
fi
if grep -w "$NAME" /tmp/user.txt &> /dev/null;then
continue
fi
RAND=$(rand)
while grep -w "$RAND" /tmp/user.txt &> /dev/null
do
RAND=$(rand)
done echo -e "$NAME\t$RAND" >>/tmp/user.txt done
echo "抓阄获奖名单如下: "
sort -rnk2 /tmp/user.txt |head -3


shell编程基础进阶的更多相关文章

  1. 【转】Shell编程基础篇-下

    [转]Shell编程基础篇-下 1.1 条件表达式 1.1.1 文件判断 常用文件测试操作符 常用文件测试操作符 说明 -d文件,d的全拼为directory 文件存在且为目录则为真,即测试表达式成立 ...

  2. 【转】Shell编程基础篇-上

    [转]Shell编程基础篇-上 1.1 前言 1.1.1 为什么学Shell Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, Linux/UNIX系统的底层及基础应 ...

  3. shell编程基础(转载)

    Shell编程基础 原作者 Leal:请参阅页面底部的编者列表. 授权许可: 创作共享署名协议 GNU 自由文档许可证 注意:本文仍然在持续的修订之中,且错漏之处可能较多.如果能够阅读英语的话,可以考 ...

  4. 【Shell 编程基础第二部分】Shell里的流程控制、Shell里的函数及脚本调试方法!

    http://blog.csdn.net/xiaominghimi/article/details/7603003 本站文章均为李华明Himi原创,转载务必在明显处注明:转载自[黑米GameDev街区 ...

  5. Linux学习之二十一-shell编程基础

    Shell编程基础 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言.Shell 是指一种应用程序,这个应用程序提供了一个 ...

  6. 7-1 shell编程基础之二

    shell编程基础之二 算数运算 bash中的算术运算:help let +, -, *, /, %取模(取余), **(乘方),乘法符号有些场景中需要转义 实现算术运算: (1) let var=算 ...

  7. 6-2 shell编程基础

    shell编程基础 编程基础 Linus:Talk is cheap, show me the code 程序和编程风格 程序: 程序:算法+数据结构 数据:是程序的核心 算法:处理数据的方式 数据结 ...

  8. Java并发编程--基础进阶高级(完结)

    Java并发编程--基础进阶高级完整笔记. 这都不知道是第几次刷狂神的JUC并发编程了,从第一次的迷茫到现在比较清晰,算是个大进步了,之前JUC笔记不见了,重新做一套笔记. 参考链接:https:// ...

  9. 基于Linux系统的Shell编程-基础篇

    1. Shell基础介绍 1.1 Shell编程的意义 为什么使用shell编程 节约时间 1.2 显示脚本执行过程 前面有+表示执行过的命令的 前面没有东西,表示输出到屏幕上的内容. [root@C ...

随机推荐

  1. flex布局的一些注意点

    现在来总结下自己在项目中用flex布局的一些注意点 1.ui图中的布局方式与justify-content的布局方法不一样 这是就要利用flex-grow的空dom来分开子容器来达到页面布局的效果 2 ...

  2. 多线程篇四:ThreadLocal实现线程范围内变量共享

    1.static实现线程范围内变量共享 package com.test.shareData; import java.util.Random; /** * 多线程范围内的数据共享 * @author ...

  3. document.write()重写问题

    document.write(); 可用于重写给某个元素追加内容; 当document.write(); 用于JS文件中,会重写整个页面,解决这个问题有多种方法. 重写原因:当onload的时候执行 ...

  4. angular2-模块

    Angular模块 (NgModule) Angular 模块是带有 @NgModule 装饰器函数的类. @NgModule接收一个元数据对象,该对象告诉 Angular 如何编译和运行模块代码. ...

  5. Android SharedPreferences存储数据

    SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-value(键值对)SharedPreferences常用来 ...

  6. Angular5+ 自定义表单验证器

    Angular5+ 自定义表单验证器 Custom Validators 标签(空格分隔): Angular 首先阐述一下遇到的问题: 怎样实现"再次输入密码"的验证(两个cont ...

  7. JavaScript 三种工厂模式

    标签(空格分隔): JavaScript 简单工厂模式是工厂函数返回实例化对象或者对象,工厂函数作为一个方法. 工厂方法模式是工厂函数不作改变,将子类放在工厂原型中:工厂函数返回对应的实例化对象:re ...

  8. Python——追加学习笔记(四)

    函数 1.python里的函数可以返回一个值或者对象,知识在返回一个容器对象的时候有点不同,看起来像是能返回多个对象. >>> def bar(): ... return 'abc' ...

  9. March 10 2017 Week 10 Friday

    If you love life, life will love you back. 爱生活,生活也会爱你. Love life, and it will love you back. All thi ...

  10. ZT acct 中文man页面(1)

    acct 中文man页面(1) 2011-08-18 13:57 佚名 博客转载 我要评论(0) 字号:T | T 如果在内核编译时开启了进程记账选项(CONFIG_BSD_PROCESS_ACCT) ...