为什么学习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. vue+rest-framework前后端分离整合(二)

    一.基于api前端显示课程详细信息 1.调整Course.vue模块 <template> <div> <h1>课程列表</h1> <div v- ...

  2. easyui datagrid 获取行数据某个字段

    首先要能获取datagrid 的row对象 即:var row = $('#datagrid').datagrid('getData').rows[index]; 之后我们就可以通过类似row.nam ...

  3. es6变量解构赋值的用途

    这里是我觉得es6解构赋值,在平时我们写js的时候非常有用,而且经常用到的地方,能简化我们的代码,让写代码简介优雅易读; 用途 1.交换变量的值,太方便了这逼,写法不仅简介而且一看就明白 let [x ...

  4. iDempiere 使用指南 绿色版一键启动测试环境

    Created by 蓝色布鲁斯,QQ32876341,blog http://www.cnblogs.com/zzyan/ iDempiere官方中文wiki主页 http://wiki.idemp ...

  5. VC6.0静态编译注意事项

    选择静态编译(工程->常规->Microsoft基础类->使用MFC作为静态链接库)的时候,会报错:MSVCRTD.lib(MSVCRTD.dll) : error LNK2005: ...

  6. 【NLP_Stanford课堂】语言模型1

    一.语言模型 旨在:给一个句子或一组词计算一个联合概率 作用: 机器翻译:用以区分翻译结果的好坏 拼写校正:某一个拼错的单词是这个单词的概率更大,所以校正 语音识别:语音识别出来是这个句子的概率更大 ...

  7. Java框架安全

    (一)Mybatis注入问题 Mybatis是目前比较常用的ORM的框架,一般与SpringMVC框架整合较多,但使用不当会有SQL注入的风险. Mybatis里mapper中SQL语句的写法支持两种 ...

  8. 两种计算Java对象大小的方法

    之前想研究一下unsafe类,碰巧在网上看到了这篇文章,觉得写得很好,就转载过来.原文出处是: http://blog.csdn.net/iter_zc/article/details/4182271 ...

  9. Flask入门模板过滤器与测试器(五)

    1 模板引擎之过滤器 概念 : 过滤器本质上是个转换函数,第一个参数是待过滤的变量.如果它有第二个参数,模板中就必须传进去. 过滤器使用管道符| 放在{{ }} Jinja2模板引擎提供了丰富的内置过 ...

  10. 最简单的nginx教程 - 如何把一个web应用部署到nginx上

    Nginx (engine x) 是一个高性能的HTTP和反向代理服务,也是一个IMAP/POP3/SMTP服务.Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Ра ...