zoukankan      html  css  js  c++  java
  • shell进阶

    shell 中的高级用法

    1.if

    单重判断

    if cmd; then
        cmd
        cmd
        cmd
    fi
    

    多重判断

    单分支

    if  cmd;then
        cmd
    elif 
        cmd
    fi
    

    双分支

    if cmd; then
        cmd
    elif cmd;then
        cmd
    elif cmd;then
        cmd
    else
        cmd
    fi
    
    

    用于当判断条件的参数

    逻辑判断

    -a && 与
    -o || 或
    ! 非
    =~ 左边变量 ,右边扩展的正则表达式,不能写双引号
    -z 判空
    == 相等
    != 不相等

    大小判断
    -eq //等于
    -ne //不等于
    -gt //大于 (greater )
    -lt //小于 (less)
    -ge //大于等于
    -le //小于等于

    文件比较符
    -e 判断对象是否存在
    -d 判断对象是否存在,并且为目录
    -f 判断对象是否存在,并且为常规文件
    -L 判断对象是否存在,并且为符号链接
    -h 判断对象是否存在,并且为软链接
    -s 判断对象是否存在,并且长度不为0
    -r 判断对象是否存在,并且可读
    -w 判断对象是否存在,并且可写
    -x 判断对象是否存在,并且可执行
    -O 判断对象是否存在,并且属于当前用户
    -G 判断对象是否存在,并且属于当前用户组
    -nt 判断file1是否比file2新 [ ``"/data/file1" -nt ``"/data/file2" ]
    -ot 判断file1是否比file2旧 [ ``"/data/file1" -ot ``"/data/file2" ]

    2.case

    要注意的是case 中使用的是引用变量,而不是声明变量名,$xxx

    case支持glob风格的通配符:
    *: 任意长度任意字符
    ?: 任意单个字符
    []:指定范围内的任意单个字符
    a|b: a或b

    case $num 变量引用 in  
    1|2|3)     判断条件 ,可以使用通配符
        cmd1;
        ;;     根据;;来结束一个case段
    4|5|6)
        cmd2;
        ;;
    *)
        cmd3;
        ;;
    esac
    

    echo $passwd | passwd stdin user 设置用户密码

    3.for

    for 变量名(不是变量引用,不带$) in 列表;do
    循环体
    done

    实例

    for num in {1..10};do
        echo num is $num;
    done
    

    列表生成方式:

    1. 直接给出列表
    2. 整数列表:
      (a) {start..end}
      (b) $(seq [start [step]] end)
    3. 返回列表的命令
      $(COMMAND)
    4. 使用glob,如:*.sh
    5. 变量引用;$@, $*

    列表可以用任意的合集,用命令解析得到的合集也可以,比如填 ls /bin,支持通配符
    {1..100..3} 1到100,每次步进3
    unset sum 删除变量sum,防止影响
    for中使用多行重定向的话 。需要把第一个EOF加- 或者把EOF结尾标志顶格。否则无法识别

    for i in {1..10};do
        cat >>f1<<-EOF
        ASDASD
        ASDASD
        EOF
    done
    

    或者

    for i in {1..10};do
        cat >>f1 <<EOF
        ASDASD
        ASDASD
    EOF
    done
    

    4.for循环的第二种格式语法

    sum=0
    for ((i=1;i<=100;i++))
    let sum+=i
    done

    for i in {1..3};do
    for j in {1..10};do
    if [ (j -eq 5 ];then continue 2;fi echo j=)j
    done
    done
    这边就表示,当j等于5的时候,跳出第二层循环 。不是j循环的第二次,而是第二层!!!就是跳出i循环的当次循环,直接执行i的下次循环

    5.参数移除

    shift n

    shift[n] 参数左移,n可以指定具体数字,表示每次抛弃的参数个数
    比如 1 2 3
    就会先处理完1,然后把1抛弃,处理2,以此类推

    6.并行执行

    并行执行 把所有语句用 {} 包裹,最后加上 & 就是把语句放在后台并行执行。

    wait 脚本执行完成后自动退出,不需要用户按回车

    为什么会输出两次192.168.30.1

    let命令特性点:如果他操作的变量值为 0 返回的是假,
    如果变量非0,返回是真

    比如 i=0
    leti++ ,那么这一次返回的是0

    unset i
    let i++
    echo $? 为 假 1
    unset i
    let ++i
    echo $? 为真 0

    n=10;seq 1 (n 这样用这个, n=10;echo {1..)n} 这样是会报错的,不能这样执行

    n=10;eval echo {1..$n} eval 会扫描并替换变量,然后执行该语句

    用花括号分割变量

    比如 (ix)j ,可能后面的(j会识别成x)j

    写成
    (ix){j} 即可

    openssl rand -base64 20 | tr -dc '[: alpha :]'|head -c8

    $[ 这样的格式里面可以做运算操作 ]

    while 条件;do
    循环体
    done

    : 返回真 等同于 true

    selinux

    用pgrep 查看进程是否存在,然后监控
    pgrep 可以匹配到返回是true(0),而匹配不到会返回false(1)

    向进程发送0信号,可以检测进程是否存在,因为0 信号不会对进程进行任何处理,但是会检查错误。

    until 条件;do
    循环体
    done

    与while相反,条件为假时进入循环,条件为真时,退出

    who |grep USERNAME 查看该用户是否登录

    7.while

    while cmd;do
    cmd
    if cmd;then
    continue 跳过当次执行
    fi
    done

    while cmd;do
    cmd
    if cmd;then
    break 退出当前循环块
    fi
    done

    continue 和 break 后面可以跟数字,用于结束第N层的循环。
    最里面的循环是第一层,往外层递增

    whlie read line;do
    循环体
    done

    while循环的特殊用法(遍历文件的每一行):
    while read line; do
    循环体
    done < /PATH/FROM/SOMEFILE
    依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line

    df | while read line;do
    处理df的每一行,支持管道
    done

    8.until 循环

    until cmd;do
        循环体
    done
    

    进入条件:cmd为假
    退出条件:cmd为真
    本质就是一个跟while相反的条件判断

    9.select 创建菜单

    PS3="Please choose the menu 1-4 : " 修改运行脚本时候的select提示符
    select variable in list
    do
    循环体命令
    done

    $REPLAY存储用户手动输入的内容

    自动将List转换为菜单,根据选择的项,给变量赋值

    PS1命令行提示符
    PS2多行重定向提示符
    PS3 select 命令提示符

    select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环
    select 经常和 case 联合使用
    与 for 循环类似,可以省略 in list,此时使用位置参量

    下面是一个简单的示例:

    #!/bin/bash
    echo "What is your favourite OS?"
    select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
      break;
    done
    echo "You have selected $var"
    </pre>
    

    该脚本的运行结果如下:

    What is your favourite OS?
        1) Linux
        2) Gnu Hurd
        3) Free BSD
        4) Other
    #? 1
    You have selected Linux</pre>
    

    10.trap 捕获信号

    trap 'echo press ctrl+c' int 捕获Int信号 ,转换为echo press ctrl +c
    trap '' # 捕获信号,并且什么都不做,相当于拦截信号
    trap '-' # 使信号恢复,恢复原信号的操作

    可以捕捉15信号,使程序不可以正常关闭。但是无法捕捉9这个强制关闭的信号

    脚本任务
    alias.sh 配置别名
    vim.sh 配置vim
    yum.sh 配置yum
    pack.sh 安装软件包

    declare -f func4 查询是否存在func4函数

    如果要在脚本里执行rm相关操作,需要检查对应的路径是否正确,变量是否赋值成功

    11.函数

    定义格式
    语法一:

    f_name ()
    {
        ...函数体...
    }
    

    语法二:

    function f_name
    {
        ...函数体...
    } 
    

    语法三:

    function f_name ()
    {
        ...函数体...
    }
    

    函数的优先级比别名高
    函数的生效范围是当前shell
    local 改变变量的有效范围,让他只在该函数内有效

    全局变量 > 普通变量 > local 变量
    declare 声明的变量,也是local 类型的
    declare -ig num=100 加g之后定义,变量就变成了普通变量,不再是local变量
    return 退出函数本身
    在函数中使用echo 输出变量 ,就可以把输出写在if中直接判断
    version (){ echo 1 }
    if [ version -eq 1 ] 判断是成立的
    add() { echo $[$1+$2] }
    add 1 2
    输出3

    函数复用

    把函数保存为bash脚本,

    新的脚本中使用
    source functions (脚本名),相当于引用该脚本

    之后就可以使用该脚本中的函数

    action "commadn successful " 可以显示成功

    action "xxx" /bin/false 表示失败
    action "xxx /bin/true 表示成功

    /etc/init.d/functions 储存了系统内置的函数

    函数可以覆盖定义

    export -f func1 将函数声明为全局函数,让子shell也可以使用该函数,定义函数的时候,不可以使用export

    函数递归调用的时候,只有递归结束的时候,才会执行递归后的操作。

    数组

    关联索引 把数组的索引设置为自定义的格式,而不仅仅是数字

    bash的数组支持稀疏索引(索引不连续),比如0,1, 3 有东西,2 没有 那么数组长度是3 ,但是他们不是连接的。输出2的话是空

    declare -a ARRAY_NAME 普通数组
    declare -A ARRAY_NAME 关联数组 必须先声明再使用

    ${a[1]}

    echo ${name[* ]}
    echo ${name[@]}
    都代表输出数组中的所有元素

    number=({1..10}) 这样也可以定义数组,()中存放任意生成多个字符串的命令都可以。通配符,正则表达式查找,bash命令,都能放

    read -a title a b c 定义数组title ,内容是a b c
    echo a b c | read -a s 定义数组s,内容是a b c (这样是错误的!!管理是不支持交互式赋值的)

    关联数组一定要先定义再使用,否则数组变量会出问题

    关联数组更像一个字典

    ${#name[* ]} 显示name数组的数组长度

    因为使用了管道,所以开启了子shell,导致变量没有值
    这样的话,在循环中使用的数组,声明周期单独只在循环中生效,因为这个时候while read line 使用的是开启的子shell

    字符串处理

    ${var#*word}

    str没有配置 表示变量不存在,没有声明

    生成随机文件名
    mktemp /data/tmpXXXXX 表示有五位的随机字符

    expect

    自动处理交互式命令,需要安装yum 包

    自动传输文件

    !/usr/bin/expect

    spawn scp /etc/fstab 192.168.8.100:/app
    expect {
    "yes/no" { send "yes ";exp_continue }
    "password" { send “magedu " }
    }
    expect eof

    spawn 表示捕获该命令 ,通过expect 来提交信息。当复制命令遇到yes或者no,就自动提交yes,然后继续执行。
    当遇到password ,提交magedu

    /etc/ssh/sshd_config

    GSSAPIAuthentication no 关闭代理 79行
    USEDNS NO 启动 115行

    修改完成后 执行 systemctl sshd restart 重启sshd服务
    加速sshd访问速度

    自动登录

    !/usr/bin/expect

    spawn ssh 192.168.8.100
    expect {
    "yes/no" { send "yes ";exp_continue }
    "password" { send “magedu " }
    }
    interact

    expect eof

    interact 表示开启交互式
    expect eof 结束expect 捕获

    interact 搭配 #expect eof 表示登录终端后,释放对ssh的控制,这样expect就不会再继续捕获命令

    expect 写一个控制脚本
    用bash调用该脚本,做批量机器处理

    矩阵转换

    vim matrix.sh     
         #!/bin/bash
    
        arr=([00]=1 [01]=2 [02]=3 [10]=4 [11]=5 [12]=6 [20]=7 [21]=8 [22]=9)
        size=3
    
        showmatrix () {
        for ((i=0;i<size;i++));do
            for ((j=0;j<size;j++));do
                echo -e "${arr[$i$j]} c"
            done
            echo
    done
    }
    
    echo "Before convert"
    
    showmatrix
    
    for ((i=0;i<size;i++));do
        for ((j=i;j<size;j++));do
            if [ $i -ne $j ];then
                temp=${arr[$i$j]}
                arr[$i$j]=${arr[$j$i]}
                arr[$j$i]=$temp
            fi
        done
    done
    
    echo "After convert"
    
  • 相关阅读:
    1062 Talent and Virtue (25 分)
    1083 List Grades (25 分)
    1149 Dangerous Goods Packaging (25 分)
    1121 Damn Single (25 分)
    1120 Friend Numbers (20 分)
    1084 Broken Keyboard (20 分)
    1092 To Buy or Not to Buy (20 分)
    数组与链表
    二叉树
    时间复杂度与空间复杂度
  • 原文地址:https://www.cnblogs.com/ddz-linux/p/10462763.html
Copyright © 2011-2022 走看看