zoukankan      html  css  js  c++  java
  • bash编程基础




    bash变量

    变量命名:
    1、不能使用程序中的关键字(保留字)
    2、只能使用数字、字母和下划线,且不能以数字开头
    3、要见名知义

    变量类型:
    数值型:精确数值(整数),近似数值(浮点型)
    字符型:char,string
    布尔型:true, false
    类型转换:显式转换,隐式转换

    按使用范围分类
    可赋值
    环境变量:对当前shell进程及其子shell有效,对其它的shell进程无效         
    定义:export VAR_NAME=VALUE
    导出:export VAR_NAME
    撤消变量:unset VAR_NAME
    只读变量:readonly VAR_NAME 
    本地变量:只对当前shell进程有效的变量,对其它shell进程无效,包当前shell进程的子进程
    VAR_NAME=VALUE
    局部变量:对shell脚本中某代码片断有效,通常用于函数本地
    local VAR_NAME=VALUE 
    不赋值
    位置变量:用来接受变量指定位置的参数
    $1,$2...,${10} 
    特殊变量:shell对一些参数做特殊处理,这些参数只能被引用而不能被赋值
    $#  传递到脚本的参数个数
    $@  与$*相同,但是使用时加引号,并在引号中返回每个参数
    $*  显示所有向脚本传递的参数   #与位置变量不同,此选项参数可超过9个
    $$  获取当前shell的进程号
    $!  执行上一个指令的进程号
    $?  获取执行的上一个指令的返回值              #0为执行成功,非零为执行失败
    $-  显示shell使用的当前选项,与set命令功能相同

    变量引用:${VAR_NAME}         
    "":弱引用,里面的变量会被替换
    '':强引用,里面的所有字符都是字面量,直接输出 

    查看变量
    set:查看当前shell进程中的所有变量
    export, printenv, env:查看当前shell进程中的所有环境变量 

    bash的配置文件
    profile类:为交互式登录的用户提供配置
    全局:/etc/profile、/etc/profile.d/*.sh
    用户:~/.bash_profile
    bashrc类:为非交互式的用户提供配置
    全局:/etc/bashrc
    用户:~/.bashrc
    功能:设定本地变量,定义命令别名


    编写与执行

    编写格式:
    shell脚本第一行必须顶格写,用shebang定义指定的解释器来解释该脚本。
    #!/bin/bash       #!即为shebang 
    其它的以#开头的行均为注释,会被解释器忽略,可用来注释脚本用途及版本,方便使用管理。

    执行方式:
    bash编程属于面向过程编程,执行方式如下:
    顺序执行:按命令先后顺寻依次执行
    选择执行:测试条件,可能会多个测试条件,某条件满足时,则执行对应的分支
    循环执行:将同一段代码反复执行多次,因此,循环必须有退出条件;否则,则陷入死循环

    bash执行选项:
    bash -n SHELLNAME  #语法测试,测试是否存在语法错误
    bash -x SHELLNAME  #模拟单步执行,显示每一步执行过程 

    算数运算与逻辑运算

    算数运算
    定义整型变量:
    let VAR_NAME=INTEGER_VALUE            #例如:let a=3
    declare -i VAR_NAME=INTEGER_VALUE     #declare -i a=3 

    实现算术运算的方式:
    let VAR_NAME=ARITHMATIC_EXPRESSION
    VAR_NAME=$[ARITHMATIC_EXRESSION]
    VAR_NAME=$((EXPRESSION))
    VAR_NAME=$(expr $num1 + $num2) 

    算术运算符:
    +:加法
    -:减法
    *:乘法
    /:整除
    %:取余数
    **:乘幂 
    注意:即使没有定义为整型变量,字符型的数字依然可以参与算术运算,bash会执行变量类型的隐式类型转换。

    逻辑运算
    布尔运算:
    真,假
    与运算:
    真 && 真 = 真
        真 && 假 = 假
        假 && 真 = 假
        假 && 假 = 假
    或运算:
    真 || 真 = 真
        真 || 假 = 真
        假 || 真 = 真
        假 || 假 = 假
    非运算:
    !真=假
        !假=真 


    条件测试

    整型测试:整数比较
    例如 [ $num1 -gt $num2 ]
    -gt: 大于则为真
    -lt: 小于则为真
    -ge: 大于等于则为真
    -le: 小于等于则为真
    -eq: 等于则为真
    -ne: 不等于则为真 

    字符测试:字符串比较
    双目:
    例如[[ "$str1" > "$str2" ]]
    >: 大于则为真
    <: 小于则为真
    >=:大于等于则为真
    <=:小于等于则为真
    ==:等于则为真
    !=:不等于则为真 
    单目:
    -n String: 是否不空,不空则为真,空则为假
    -z String: 是否为空,空则为真,不空则假 

    文件测试:判断文件的存在性及属性等
    -a FILE:存在则为真;否则则为假;
    -e FILE: 存在则为真;否则则为假;
    -f FILE: 存在并且为普通文件,则为真;否则为假;
    -d FILE: 存在并且为目录文件,则为真;否则为假;
    -L/-h FILE: 存在并且为符号链接文件,则为真;否则为假;
    -b: 存在并且为块设备,则为真;否则为假;
    -c: 存在并且为字符设备,则为真;否则为假
    -S: 存在并且为套接字文件,则为真;否则为假
    -p: 存在并且为命名管道,则为真;否则为假
    -s FILE: 存在并且为非空文件则为值,否则为假;
    -r FILE:文件可读为真,否则为假
    -w FILE:文件可写为真,否则为假
    -x FILE:文件可执行为真,否则为假
    file1 -nt file2: file1的mtime新于file2则为真,否则为假;
    file1 -ot file2:file1的mtime旧于file2则为真,否则为假; 

    组合条件测试:在多个条件间实现逻辑运算
    与:
    [ condition1 -a condition2 ]
    condition1 && condition2
    或:
    [ condition1 -o condition2 ]
    condition1 || condition2
    非:
    [ -not condition ]
    ! condition

    与:
    COMMAND1 && COMMAND2
    COMMAND1如果为假,则COMMAND2不执行
    或:
    COMMAND1 || COMMAND2
    COMMAND1如果为真,则COMMAND2不执行
    非:
    ! COMMAND 


    分支结构

    if之单分支
    语句结构:
    if 测试条件;then
       选择分支
    fi 
    表示条件测试状态返回值为值,则执行选择分支
    例:写一个脚本,接受一个参数,这个参数是用户名;如果此用户不存在,则创建该用户;
    if ! id $1 &> /dev/null;then
        useradd $1
    fi 

    if之双分支
    语句结构:
    if 测试条件;then
       选择分支1
    else
       选择分支2
    fi 
    两个分支仅执行其中之一
    例:通过命令行给定一个文件路径,而后判断:如果此文件中存在空白行,则显示其空白行的总数;否则,则显示无空白行;
    if grep "^[[:space]]*$" $1 &> /dev/null; then
        echo "$1 has $(grep "^[[:space]]*$" $1 | wc -l) blank lines."
    else
        echo "No blank lines"
    fi 
    注意:如果把命令执行成功与否当作条件,则if语句后必须只跟命令本身,而不能引用。

    补充:bash交互式编程read
    read [option] “prompt”
    -p:直接指定一个变量接受参数
    -t timaout:指定等待接受参数的时间
    -n:表示不换行 
    例:输入用户名,可返回其shell
    read -p "Plz input a username: " userName
    if id $userName &> /dev/null; then
        echo "The shell of $userName is `grep "^$userName>" /etc/passwd | cut -d: -f7`."
    else
        echo "No such user. stupid."
    fi 

    if之多分支
    语句结构:
    if 条件1;then
         分支1
    elif 条件2;then
         分支2
    elif 条件3;then
         分支3
          ...
    else
         分支n
    fi 

    例:传递一个用户名给脚本:如果此用户的id号为0,则显示说这是管理员;如果此用户的id号大于等于500,则显示说这是普通用户;否则,则说这是系统用户。
    if [ $# -lt 1 ]; then
        echo "Usage: `basename $0` username"
        exit 1
    fi
    if ! id -u $1 &> /dev/null; then
        echo "Usage: `basename $0` username"
        echo "No this user $1."
        exit 2
    fi
    if [ $(id -u $1) -eq 0 ]; then
        echo "Admin"
    elif [ $(id -u $1) -ge 500 ]; then
        echo "Common user."
    else
        echo "System user."
    fi 

    case语句:有多个测试条件时,case语句会使得语法结构更明晰
    语句结构:
    case 变量引用 in
    PATTERN1)
        分支1
    ;;
    PATTERN2)
        分支2
    ;;
    ...
    *)
        分支n
    ;;
    esac 
    PATTERN:类同于文件名通配机制,但支持使用|表示或者
    a|b: a或者b
    *:匹配任意长度的任意字符
    ?: 匹配任意单个字符
    []: 指定范围内的任意单个字符 

    例:写一个脚本,完成如下任务,其使用形式如下所示:
    script.sh {start|stop|restart|status}
    其中:
    如果参数为空,则显示帮助信息,并退出脚本;
    如果参数为start,则创建空文件/var/lock/subsys/script,并显示“starting script successfully.”
    如果参数为stop,则删除文件/var/lock/subsys/script,并显示“Stop script successfully.”
    如果参数为restart,则删除文件/var/locksubsys/script并重新创建,而后显示“Restarting script successfully.”
    如果参数为status,那么:如果文件/var/lock/subsys/script存在,则显示“Script is running...”,否则,则显示“Script is stopped.”
    #!/bin/bash
    file='/var/lock/subsys/script'
    case $1 in
    start)
     if [ -f $file ];then
    echo "Script is running..."
     exit 3
     else
    touch $file
    [ $? -eq 0 ] && echo "Starting script successfully."
     fi
     ;;
    stop)
     if [ -f $file ];then
    rm -rf $file
    [ $? -eq 0 ] && echo "Stop script successfully."
     else
    echo "Script is stopped..."
    exit 4
     fi
     ;;
    restart)
     if [ -f $file ];then
    rm -rf $file
    [ $? -eq 0 ] && echo "Stop script successfully"
     else 
    echo "Script is stopped..."
    exit 5
     fi
    touch $file
    [ $? -eq 0 ] && echo "Starting script successfully"
     ;;
    status)
     if [ -f $file ];then
    echo "Script is running..."
     else
    echo "Script is stopped."
     fi
     ;;
    *)
    echo "`basename $0` {start|stop|restart|status}"
    exit 2
     ;;
    esac 


    循环

    for语句格式一
    语句结构:
    for 变量名 in 列表; do
        循环体
    done 
    列表:可包含一个或多个元素
    循环体:依赖于调用变量来实现其变化
    循环可嵌套
    退出条件:遍历元素列表结束

    例:求100以内所有正整数之和
    #!/bin/bash
    declare -i sum=0
    for i in {1..100}; do
        let sum+=$i
    done
    echo $sum 


    for语句格式二
    for ((初始条件;测试条件;修改表达式)); do
          循环体
    done 
    先用初始条件和测试条件做判断,如果符合测试条件则执行循环体,再修改表达式,否则直接跳出循环。

    例:求100以内所有正整数之和(for二实现)
    #!/bin/bash
    declare -i sum=0
    for ((counter=1;$counter <= 100; counter++)); do
        let sum+=$counter
    done
    echo $sum 


    while语句
    while适用于循环次数未知,或不便用for直接生成较大的列表时
    语句结构:
    while 测试条件; do
        循环体
    done 
    测试条件为真,进入循环;测试条件为假,退出循环

    例:求100以内所有偶数之和,要求使用取模方法
    #!/bin/bash
    declare -i counter=1
    declare -i sum=0
    while [ $counter -le 100 ]; do
        if [ $[$counter%2] -eq 0 ]; then
             let sum+=$counter
        fi
        let counter++
    done
    echo $sum 

    例:提示用户输入一个用户名,如果用户存在,就显示用户的ID号和shell;否则显示用户不存在;显示完成之后不退出,再次重复前面的操作,直到用户输入q或quit为止
    #!/bin/bash
    read -p "Plz enter a username: " userName
    while [ "$userName" != 'q' -a "$userName" != 'quit' ]; do
        if id $userName &> /dev/null; then
           grep "^$userName>" /etc/passwd | cut -d: -f3,7
        else
            echo "No such user."
        fi
    read -p "Plz enter a username again: " userName
    done 


    while特殊用法:遍历文本文件
    语句结构:
    while read 变量名; do
        循环体
    done < /path/to/somefile 
    变量名,每循环一次,记忆了文件中一行文本

    例:显示ID号为偶数,且ID号同GID的用户的用户名、ID和SHELL
    while read line; do
        userID=`echo $line | cut -d: -f3`
        groupID=`echo $line | cut -d: -f4`
        if [ $[$userID%2] -eq 0 -a $userID -eq $groupID ]; then
             echo $line | cut -d: -f1,3,7
        fi
    done < /etc/passwd 


    until语句
    语句结构:
    until 测试条件; do
          循环体
    done 
    测试条件为假,进入循环;测试条件为真,退出循环

    例:求100以内所有偶数之和,要求使用取模方法(until实现)
    #!/bin/bash
    declare -i counter=1
    declare -i sum=0
    until [ $counter -gt 100 ]; do
        if [ $[$counter%2] -eq 0 ]; then
             let sum+=$counter
        fi
        let counter++
    done
    echo $sum 

    例:提示用户输入一个用户名,如果用户存在,就显示用户的ID号和shell;否则显示用户不存在;显示完成之后不退出,再次重复前面的操作,直到用户输入q或quit为止(until实现)
    #!/bin/bash
    read -p "Plz enter a username: " userName
    until [ "$userName" = 'q' -a "$userName" = 'quit' ]; do
        if id $userName &> /dev/null; then
           grep "^$userName>" /etc/passwd | cut -d: -f3,7
        else
            echo "No such user."
        fi
    read -p "Plz enter a username again: " userName
    done 

    循环之循环控制和shift

    循环控制命令:
    break:提前退出循环
    break [N]: 退出N层循环;N省略时表示退出break语句所在的循环
    continue: 提前结束本轮循环,而直接进入下轮循环
    continue [N]:提前第N层的循环的本轮循环,而直接进入下轮循环

    死循环:
    #while体
    while true; do
          循环体
    done
    #until体
    until false; do
          循环体
    done 

    例:写一个脚本,判断给定的用户是否登录了当前系统
    (1) 如果登录了,则脚本终止;
    (2) 每5秒种,查看一次用户是否登录;
    #!/bin/bash
    while true; do
        who | grep "gentoo" &> /dev/null
        if [ $? -eq 0 ];then
    break
        fi
        sleep 5
    done
    echo "gentoo is logged." 

    shift:
    如果没有数字,只有shift 就是跳过一个参数获取下一个参数,如果加上数字,比如shift 2 ,跳过两个参数获取下一个参数。
    例:写一个脚本,使用形式如下所示    
    showifinfo.sh [-i INTERFACE|-a] [-v]
    要求:
    1、-i或-a不可同时使用,-i用于指定特定网卡接口,-a用于指定所有接口;
    显示接口的ip地址
    2、使用-v,则表示显示详细信息
    显示接口的ip地址、子网掩码、广播地址;
    3、默认表示仅使用-a选项;
    #!/bin/bash
    allinterface=0
    ifflag=0
    verbose=0
    interface=0
    if [ $# -eq 0 ];then
        ifconfig | grep "inet addr:" | awk '{print $2}'
    fi
    while [ $# -ge 1 ];do
      case $1 in
      -a)
        allinterface=1
        shift 1
      ;;
      -i)
        ifflag=1
        interface=$2
        shift 2
      ;;
      -v)
        verbose=1
        shift 1
      ;;
      *)
        echo "error option"
        exit 2
      ;;
      esac
    done
    if [ $allinterface -eq 1 ];then
      if [ $ifflag -eq 1 ];then
          echo "command not found"
          exit 5
      fi
      if [ $verbose -eq 1 ];then
          ifconfig | grep "inet addr:"
      else
          ifconfig | grep "inet addr:" | awk '{print $2}'
      fi
    fi
    if [ $ifflag -eq 1 ];then
      if [ $allinterface -eq 1 ];then
            echo "command not found"
            exit 5
      fi
      if [ $verbose -eq 1 ];then
          ifconfig $interface | grep "inet addr:"
      else
          ifconfig $interface | grep "inet addr:" | awk '{print $2}'
      fi
    fi 



    函数

    语法结构:
    function F_NAME {
            函数体
    }
    F_NAME() {
            函数体
    可调用:使用函数名,函数名出现的地方,会被自动替换为函数
    函数的返回值:
    函数的执行结果返回值:代码的输出
    函数中使用打印语句:echo, printf
    函数中调用的系统命令执行后返回的结果
    执行状态返回值:
    默认取决于函数体执行的最后一个命令状态结果
    自定义退出状态码:return [0-255]
    注意:函数体运行时,一旦遇到return语句,函数即返回;

    函数可以接受参数:
    在函数体中调用函数参数的方式同脚本中调用脚本参数的方式:位置参数
    $1, $2, ...
    $#, $*, $@

    例:写一个脚本,完成如下功能(使用函数):
    1、提示用户输入一个可执行命令;
    2、获取这个命令所依赖的所有库文件(使用ldd命令);
    3、复制命令至/mnt/sysroot/对应的目录中
    解释:假设,如果复制的是cat命令,其可执行程序的路径是/bin/cat,那么就要将/bin/cat复到/mnt/sysroot/bin/目录中,如果复制的是useradd命令,而useradd的可执行文件路径为/usr/sbin/useradd,那么就要将其复制到/mnt/sysroot/usr/sbin/目录中;
    4、复制各库文件至/mnt/sysroot/对应的目录中;
    #!/bin/bash
    target=/mnt/sysroot/
    [ -d $target ] || mkdir $target
    preCommand() {
        if which $1 &> /dev/null; then
    commandPath=`which --skip-alias $1`
    return 0
        else
    echo "No such command."
    return 1
        fi
    }
    commandCopy() {
        commandDir=`dirname $1`
        [ -d ${target}${commandDir} ] || mkdir -p ${target}${commandDir}
        [ -f ${target}${commandPath} ] || cp $1 ${target}${commandDir}
    }
    libCopy() {
        for lib in `ldd $1 | egrep -o "/[^[:space:]]+"`; do
        libDir=`dirname $lib`
        [ -d ${target}${libDir} ] || mkdir -p ${target}${libDir}
        [ -f ${target}${lib} ] || cp $lib ${target}${libDir}
        done
    read -p "Plz enter a command: " command
    until [ "$command" == 'quit' ]; do
      if preCommand $command &> /dev/null; then
        commandCopy $commandPath
        libCopy $commandPath
      fi
      read -p "Plz enter a command: " command
    done 


    信号捕捉

    trap命令用于在shell程序中捕捉到信号,之后可以有三种反应方式:
    (1)执行一段程序来处理这一信号
    (2)接受信号的默认操作
    (3)忽视这一信号

    trap对上面三种方式提供了三种基本形式:
    第一种形式的trap命令在shell接收到signal list清单中数值相同的信号时,将执行双引号中的命令串。
    trap 'commands' signal-list
    trap "commands" signal-list
    第二种形式的trap命令恢复信号的默认操作:trap signal-list
    第三种形式的trap命令允许忽视信号:trap " " signal-list
    trap 'COMMAND' SIGINT(表示关闭进程)

    例:写一个脚本,能够ping探测指定网络内的所有主机是否在线,当没有执行完时可接收ctrl+c命令退出。
    #!/bin/bash
    quitScript() {
         echo "Quit..."
    }    
    trap 'quitScript; exit 5' SIGINT
    cnetPing() {
        for i in {1..254}; do
            if ping -c 1 -W 1 $1.$i &> /dev/null; then
                echo "$1.$i is up."
             else
                echo "$1.$i is down."
            fi
            done
    }
    bnetPing() {
        for j in {0..255}; do
            cnetPing $1.$j 
        done
    }
    anetPing() {
        for m in {0..255}; do
            bnetPing $1.$m
        done
    }
    netType=`echo $1 | cut -d"." -f1`
    if [ $netType -ge 1 -a $netType -le 126 ]; then
        anetPing $netType
    elif [ $netType -ge 128 -a $netType -le 191 ]; then
        bnetPing $(echo $1 | cut -d'.' -f1,2)
    elif [ $netType -ge 192 -a $netType -le 223 ]; then
        cnetPing $(echo $1 | cut -d'.' -f1-3)
    else
        echo "Wrong"
        exit 2
    fi 


    数组

    数组:连续的多个独立内存空间,每个内存空间相当于一个变量
    数组元素:数组名+索引(从0开始编号)
    索引的表示方式:a[0], a[1]

    声明:
    声明普通数组:declare -a ARRAR_NAME
    声明关联数组:declare -A ARRAY_NAME
    支持稀疏格式:仅一维数组  

    数组元素的赋值:
    (1) 一次只赋值一个元素
    a[0]=$RANDOM
    ...
    (2) 一次赋值全部元素
    a=(red blue yellow green)
    (3) 指定索引进行赋值
    a=([0]=green [3]=red [2]=blue [6]=yellow)
    (4) 用户输入
    read -a ARRAY

    数组的访问:
    用索引访问:ARRAY[index]
    数组的长度:
    ${#ARRAY[*]}
    ${#ARRAY[@]}

    例:写一个脚本,生成10个随机数,保存至数组中;而后显示数组下标为偶数的元素
    #!/bin/bash
    for i in {0..9}; do
        rand[$i]=$RANDOM
        [ $[$i%2] -eq 0 ] && echo "$i:${rand[$i]}"
    done 

    从数组中挑选某元素:
    ${ARRAY[@]:offset:number}
    切片:
    offset: 偏移的元素个数
    number: 取出的元素的个数
    ${ARRAY[@]:offset}:取出偏移量后的所有元素
    ${ARRAY[@]}: 取出所有元素

    数组复制:
    要使用${ARRAY[@]}
    $@: 每个参数是一个独立的串
    $*: 所有参数是一个串

    向数组中追加元素:非稀疏格式
    week, 
    week[${#week[@]}]

    从数组中删除元素:
    unset ARRAY[index]

    例:复制一个数组中下标为偶数的元素至一个新数组中
    #!/bin/bash
    declare -a mylogs
    logs=(/var/log/*.log)
    echo ${logs[@]}
    for i in `seq 0 ${#logs[@]}`; do
        if [ $[$i%2] -eq 0 ];then
            index=${#mylogs[@]}
             mylogs[$index]=${logs[$i]}
        fi
    done
    echo ${mylogs[@]} 

    例:生成10个随机数,升序排序
    #!/bin/bash
    for((i=0;i<10;i++))
    do
        rnd[$i]=$RANDOM
    done
    echo -e "total=${#rnd[@]} ${rnd[@]} Begin to sort"
    for((i=9;i>=1;i--))
    do
            for((j=0;j<i;j++))
        do
        if [ ${rnd[$j]} -gt ${rnd[$[$j+1]]} ] ;then
            swapValue=${rnd[$j]}
            rnd[$j]=${rnd[$[$j+1]]}
            rnd[$[$j+1]]=$swapValue     
        fi
        done
    done
    echo ${rnd[@]} 

    例:打印九九乘法表
    #!/bin/bash
    for((i=1;i<=9;i++))
    do 
    strLine=""
        for((j=1;i<=9;j++))
        do
            strLine=$strLine"$i*$j="$[$i*$j]" "
            [ $i -eq $j ] && echo -e $strLine && break
        done
    done 

    字符串操作

    字符串切片
    ${string:offset:length}
    举例:
    string='hello word'
    echo ${string:2:4}
    llo 

    取尾部的指定个数的字符:
    ${string: -length}
    举例:
    echo ${string: -2}
    rd 

    取子串:基于模式
    ${variable#*word}:在variable中存储字串上,自左而右,查找第一次出现word,删除字符开始至此word处的所有内容;
    ${variable##*word}:在variable中存储字串上,自左而右,查找最后一次出现word,删除字符开始至此word处的所有内容;
    举例:
    file='/var/log/messages'
    ${file#*/}: 返回的结果是var/log/messages
    ${file##*/}: 返回messages 

    ${variable%word*}: 在variable中存储字串上,自右而左,查找第一次出现word,删除此word处至字串尾部的所有内容;
    ${variable%%world*}:在variable中存储字串上,自右而左,查找最后一次出现word,删除此word处至字串尾部的所有内容;
    举例:
    file='/var/log/messages'
    ${file%*/}: 返回的结果是/var/log
    ${file%%*/}: 返回结果为空 

    例:url="http://www.redhat.com:80" 
    取端口:${url##*:}
    取协议:${url%%:*} 

    查找替换:
    ${variable/pattern/substi}: 替换第一次出现
    #userinfo=`tail -1 /etc/passwd
    #echo $userinfo
    scholar:x:500:500:scholar:/home/scholar:/bin/bash
    #echo ${userinfo/scholar/redhat}
    redhat:x:500:500:scholar:/home/scholar:/bin/bash 

    ${variable//pattern/substi}:替换所有的出现
    #echo ${userinfo//scholar/redhat}
    redhat:x:500:500:redhat:/home/redhat:/bin/bash 

    ${variable/#pattern/substi}:替换行首被pattern匹配到的内容
    #echo ${userinfo/#scholar/redhat}
    redhat:x:500:500:scholar:/home/scholar:/bin/bash 

    ${variable/%pattern/substi}:替换行尾被pattern匹配到的内容
    #echo ${userinfo/%bash/redhat}
    scholar:x:500:500:scholar:/home/scholar:/bin/redhat 

    pattern可以使用globbing中的元字符:* ?

    查找删除:
    ${variable/pattern}:删除第一次出现
    #echo ${userinfo/scholar}
    :x:500:500:scholar:/home/scholar:/bin/bash 

    ${variable//pattern}:删除所有的出现
    #echo ${userinfo//scholar}
    :x:500:500::/home/:/bin/bash 

    ${variable/#pattern}:删除行首被pattern匹配到的内容
    #echo ${userinfo/#scholar}
    :x:500:500:scholar:/home/scholar:/bin/bash 

    ${variable/%pattern}:删除行尾被pattern匹配到的内容
    #echo ${userinfo/%bash}
    scholar:x:500:500:scholar:/home/scholar:/bin/ 


    大小写转换:
    小-->大:${variable^^}
    #echo ${userinfo^^}
    SCHOLAR:X:500:500:SCHOLAR:/HOME/SCHOLAR:/BIN/BASH 

    大-->小:${variable,,}
    #name="SCHOLAR"
    #echo ${name,,}
    scholar 


    变量赋值操作:
    ${variable:-string}:variable为空或未设定,那么返回string,否则,返回variable变量的值;
    ${variable:=string}:variable为空或未设定,则返回string,且将string赋值给变量variable,否则,返回variable的值;
    为脚本使用配置文件,并确保某变量有可用值的方式
    variable=${variable:-default vaule}

    写个脚本,配置etc目录;
    (1) 在配置文件中定义变量;
    (2) 在脚本中source配置文件;
    #!/bin/bash
    [ -f /etc/sysconfig/network ] && source /etc/network/network
    [-z "$HOSTAME" -o "$HOSTNAME" = '(none)' ] || HOSTNAME ='localhost'
    /bin/hostname $HOSTNAME
    /bin/hostname 


    补充

    mktemp命令:

    mktemp [OPTIONS] filename.XXX
    -d: 创建临时目录
    --tmpdir=/path/to/somewhere :指定临时文件所在的目录 

    mktemp /tmp/tmp.XXX                    #XXX生成相同数量随机字符
    mktemp --tmpdir=/var/tmp tmp.XXX       #指定目录创建临时文件
    mktemp --tmpdir=/var/tmp -d tmp.XXX    #指定目录创建临时目录 


    install命令:
    install [OPTIONS] SOURCE DEST
    install [OPTIONS] SOURCE... DIR
    install [OPTIONS] -d DIR ...

    增强型的复制命令:
    -o OWNER
    -g GROUP
    -m MODE 
    -d : 创建目录 

    install /etc/fstab /tmp                 #复制文件到指定目录
    install --mode=644 /etc/fstab /tmp/     #复制时指定权限
    install --owner=scholar /etc/fstab /tmp #复制时指定属主
    install --group=scholar /etc/fstab /tmp #复制时指定属组
    install -d /tmp/install                 #创建目录 





  • 相关阅读:
    Unique Binary Search Trees——LeetCode
    Binary Tree Inorder Traversal ——LeetCode
    Maximum Product Subarray——LeetCode
    Remove Linked List Elements——LeetCode
    Maximum Subarray——LeetCode
    Validate Binary Search Tree——LeetCode
    Swap Nodes in Pairs——LeetCode
    Find Minimum in Rotated Sorted Array——LeetCode
    Linked List Cycle——LeetCode
    VR AR MR
  • 原文地址:https://www.cnblogs.com/tsw1107/p/a448aa8e3b389f711f61d302b235d71c.html
Copyright © 2011-2022 走看看