Shell进阶脚本70个练习

目录

1.数组的基本脚本

2.子shell与父shell

3.子shell与父shell进阶

4.基础函数

5.函数进阶之作用域域返回值

6.进程控制与文件描述和管道

7.排序算法

8.花阔号的使用

9.波浪号

10.变量替换

11.高级变量替换

12.命令替换

13.算术替换

14.进程替换

15.单词切割

16.路径替换

17.随机获取密码

18.shell解释器和属性

19.初始化命令shopt终端与tput终端

20.trap信号捕捉

21.shell脚本内容排错与进度条

22.xargs参数传参

23.shift移动参数

24.其他


1.数组的基本脚本

#!/bin/bash
name[0]="jacob"       # 定义一个数组
name[1]="Rose"        # 附加数组
name[2]="Rick"        # 附加数组
name[3+3]="TinTin"    # 追加数组,相当与在第6位追加
echo ${name[0]}       # 打印数组第一个内容
echo ${name[1]}       # 打印数组第二个内容
echo ${name[6]}       # 打印数组第四个内容或echo ${name[3+3]}
name[3+3]="Tin"       # 如果有值则是修改
echo ${name[*]}       # 打印数组所有值,会把值当成一个整体
echo ${name[-1]}      # 打印数组最后一个值
echo ${name[-2]}      # 打印数组最后第二个值
echo ${#name[*]}      # 打印数组内的值的个数
echo ${name[@]}       # 打印数组所有值,分为单个个体
i=1
addr[$i]="shanghai"   # 变量名不能用变量定义,但数组内的索引可以
​
name1=(jacob Rose Rick TinTin)  # 数组还可以用这样定义
echo ${!name1[*]}     # 获取所有数组的索引或echo ${!name1[@]} 
​
root=$(df / |tail -n +2)  # 定义一个命令数组变量
echo ${root[*]}       # 打印该命令数组所有值
echo ${root[1]}       # 打印该命令数组第二个值

# 数组进阶---------------关联数组
#!/bin/bash
daclare -A man    # 声明数组是关联数组
# 定义关联数组
man[name]=TOM
man[age]=23
man[addr]=shangzheng
man[phon]=12345678987
​
echo ${man[*]}    # 打印所有关联数组的值
​
woman=([name]=lisi [age]=25 [addr]=shaoyan [phon]=98765432123)  # 或者可以这么>定义
unset woman[age]  # 删除数组内的某个键
unset woman       # 删除数组


###--------------脚本1------------------
#!/bin/bash
# 遍历数组内容
name=(zhansan lisi wanger fudo)
for i in "${name[@]}"
do
    echo $i
done
​
###--------------脚本2------------------
#!/bin/bash
# 遍历数组下标,并根据小标打印出数组的值
for i in ${!name[@]}
do
    echo ${name[i]}
done
​
###--------------脚本3------------------
#!/bin/bash
# 遍历数组下标,用while循环的方式循环
i=0
while [ $i -le ${#name[@]} ]
do
    echo ${name[i]}
    let i++
done
​
###--------------脚本4------------------
#!/bin/bash
# 取出关联数组的值
declare -A woman
woman=([name]=zhangsan [age]=45 [addr]=shan [phon]=1111111111)
# echo ${!woman[*]}    # 此时取出的是关联数组名,值不会取出
for i in ${!woman[@]}
do
    echo ${woman[$i]}
done
​

2.子shell与父shell

###--------------脚本1------------------###
#!/bin/bash
hi="hello"
echo "++++++++++++++++++++++++++++"
echo "+        我是父shell       +"
echo "++++++++++++++++++++++++++++"
echo "PWD=$PWD"
echo "bash_subshll=$BASH_SUBSHELL"     # 当前父shell是0
​
# 通过()开启子shell
(
sub_hi="I am a subshell"
echo -e "\t+++++++++++++++++++++++"
echo -e "\t    进入子shell       +"
echo -e "\t+++++++++++++++++++++++"
echo -e "\tPWD=$PWD"
echo -e "\tbash_subshll=$BASH_SUBSHELL" # 当前子shell是1
echo -e "\thi=$hi"
echo -e "\tsub_hi=$sub_hi"              # 此时在子shell中定义的变量可以打印
cd /etc;echo -e "\tPWD=$PWD"
)
​
echo "++++++++++++++++++++++++++++"
echo "+        返回父shell       +"
echo "++++++++++++++++++++++++++++"
echo "PWD=$PWD"
echo "hi=$hi"
echo "sub_hi=$sub_hi"                   # 此时在子shell中定义的变量不可以打印
echo "bash_subshll=$BASH_SUBSHELL"      # 返回父shell就是0
​
###--------------脚本2------------------###
#!/bin/bash
hi="hello"
echo "++++++++++++++++++++++++++++"
echo "+        我是父shell       +"
echo "++++++++++++++++++++++++++++"
echo "bash_subshll=$BASH_SUBSHELL" 
# 通过()开启子shell
(
echo -e "\t+++++++++++++++++++++++"
echo -e "\t+    进入子shell       +"
echo -e "\t+++++++++++++++++++++++"
echo -e "\tbash_subshll=$BASH_SUBSHELL"
     (
      echo -e "\t\t+++++++++++++++++++++++"
      echo -e "\t\t+    进入子shell       +"
      echo -e "\t\t+++++++++++++++++++++++"
echo -e "\t\tbash_subshll=$BASH_SUBSHELL"
pstree | grep subshell
      )
)
echo "++++++++++++++++++++++++++++"
echo "+        返回父shell       +"
echo "++++++++++++++++++++++++++++"
echo "bash_subshll=$BASH_SUBSHELL"
​
​
###--------------脚本3------------------###
#!/bin/bash
# 使用管道开启子shell
sum=0
df | grep "^/"|while read name total used free other
do
    echo "free=$free"
    let sum+=free  
    echo "sum=$sum"
done
echo $sum
# 注意此时如果是0的话就是错误
​
###--------------脚本4------------------###
# 如果不想起子shell则不要用管道
#!/bin/bash
tmp_file="/tmp/subshell-$$.txt"
df | grep "^/" > $tmp_file
while read name total used free other
do
    let sum+=free
done < $tmp_file
rm -rf $tmp_file
echo $sum


###--------------脚本5------------------###
# 加载其他外部命令或加载其他变量的脚本也会开启子shell
#!/bin/bash
file="/etc/passwd"
password="I-have-a-dream"
error_info="Please try again later"
# 另起一个脚本
#!/bin/bash
pstree
bash /root/shell.sh/env.sh
echo "passwd=$password"    # 当执行的是bash后,子进程进入后就会退出所以变量不会有
echo "Error:$error_info"
​
source ./env.sh            # 当执行的是source后,不会进入子进程所以变量会一直存在
echo "passwd=$password"
echo "Error:$error_info"
​
###--------------脚本6------------------###
#!/bin/bash
# 使用&在后台开启子shell
count=0
for i in {1..254}
do
    ping -c1 -i0.2 -W1 172.17.0.$i && let count++ &
done
echo $coun

3.子shell与父shell进阶

1)fork方式

使用绝对路径或相对路径执行一个命令时,都会由父进程开启一个子进程

#!/bin/bash
sleep 5
/root/shell.sh/env.sh
cd /root/shell.sh/; ./env.sh
# 调用外部命令时会fork子进程,env.sh脚本就只有一个pstree

2)exec方式

使用exec不会开启子进程,而是使用新的程序替换当前shell环境,一般使用先把exec写入另外一个脚本,使用fork方式调用exec脚本

#!/bin/bash
# 使用exec方式调用外部命令或脚本
exec ls
echo "test"   # 此时不会执行,因为现在整个脚本只会执行ls
cd /etc       # 不会执行整个脚本只会执行ls
# 注意:当exec后面的参数是文件重定向时,不会替换当前shell,脚本后面也就不会有影响

3)source方式

可以不开启子shell,而是当前shell环境中将需要执行的命令加载进来,执行完加载命令之后,继续执行脚本后续指令

#!/bin/bash
# 使用source加载外部脚本
source /root/shell.sh/env.sh
echo "hi $password"
ls /
# source将env.sh脚本的内容加载到当前shell而,后面的直接调用

4.基础函数

###--------------脚本1------------------###
#!/bin/bash
# 定义函数.............................
mymkdir () {
mkdir /root/shell.sh/test
touch /root/shell.sh/test/hi.txt
}
​
mymkdir              # 调用函数
unset mymkdir        # 取消函数定义
​

###--------------脚本2------------------###
# 调用函数
#!/bin/bash
function print_usage() {
       cat << EOF
    Usage: --help | -h
      Print help information for script
    Usage: --memory | -m
      Monitor memory information
    Usage: --network | -n
      Monitor network interface information
EOF
}
case $1 in
--memory|-m)
        free;;
--network|-n)
        ip -s link;;
--help|-h)
        print_usage;;
*)
        print_usage
esac
​
###--------------脚本3------------------###
# 定义函数位置变量
mymkdir() {
mkdir -p $1
touch $1/$2;
}
mymkdir $1 $2   # 调用

5.函数进阶之作用域域返回值

###--------------脚本1------------------###
# 默认函数启动都是不开启子shell的,所以当外函数外定义变量函数内也可以用甚至可以修改,在函数内定义变量亦然;注:次变量与export声明的变量还是有区别的,只在当前shell有效
#!/bin/bash
# 默认定义变量为当前Shell中全局有效
global_var1="hello"
global_var2="world"
​
# 定义demo函数,在函数内定义新的变量,并修改函数。 
function demo() {
     echo -e "\033[46mfunction [demo] started....\033[0m"
     func_var="Topic"
     global_var2="this is xiugai"
     echo "$global_var1 $global_var2"
     echo -e "\033[46mfunction [demo] end.\033[0m"
}
demo
echo
echo -e "func_var=$func_var \nglobal_var1=$global_var1 \nglobal_var2=$global_var2"
# 此时发现变量global_var2修改了

​
###--------------脚本2------------------###
# 在函数内加入local就会声明局部变量,就不会修改外部的变量了
#!/bin/bash
global_var1="hello"
global_var2="world"
function demo() {
     echo -e "\033[46mfunction [demo] started....\033[0m"
     local global_var2="this is xiugai" # 这里声明局部变量local
     echo "$global_var1 $global_var2"
     echo -e "\033[46mfunction [demo] end.\033[0m"
}
demo
echo
echo "$global_var1 $global_var2"
## 注意函数不调用函数内定义的函数就不会生效
​
​
###--------------脚本3------------------###
# 注:如果在函数内写exit就会退出整个脚本,但是用return设置返回值就不会退出脚本,
#!/bin/bash
function demo1() {
      uname -r
}
​
demo2() {
     echo "start demo2"
     return
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值