脚本百例—5:关于[ ]、{ }、( )以及$#&|等符号的解释
标签搜索

脚本百例—5:关于[ ]、{ }、( )以及$#&|等符号的解释

mrui
2024-09-24 / 0 评论 / 58 阅读 / 正在检测是否收录...
  • 完整的变量引用语法,不仅要包括$,还要再变量名周围加上花括号。

    cat /tmp/rep${FN}port.txt 

    因为shell变量只包含字母数字和下划线,所以很多时候并不需要使用花括号来界定变量名。任何空白字符或标点符号(下划线除外)都足以提示变量名的结束位置。但只要有疑问,就应该用花括号。

  • 位置变量。在命令行上,出现在脚本名称之后的任意单词都可以在脚本中做为编号变量被访问。$1表示第一个位置变量,$2表示第二个位置变量。10以内的位置变量可以不用加花括号,除非要区分变量名与其后出现的文本。如果涉及两位数及以上的位置变量,如${10},则必须使用花括号,否则shell会把$10解释为${1}后面紧跟着数字0.

  • 特殊的shell变量
    $*:当前脚本或函数的位置参数。如果没有使用双引号,每个单词会被进一步分割和扩展。(每个位置参数会被扩展成独立的单词,这些单词会接着进行单词分割和路径名扩展。)如果使用了双引号引用,则返回单个字符串,其中各个参数之间以$IFS(一般为空格)的第一个字符分割(如"arg1 arg2 arg3")。
    $@:当前脚步或函数的位置参数,以双引号引用的字符串列表形式出现(如"arg1" "arg2" "arg3")。准确的说,出现在双引号("@")时,@会被扩展为以双引号引用的字符串列表形式。
    $#:当前脚本或函数的参数个数。
    $$:shell的进程ID。
    $0:shell或者shell脚本的名称
    $IFS:内部字段分隔符:作为单词分隔符的一系列字符。通常设置为空格、制表符、换行符

  • ${#}、${#VAR}、${VAR#alt}区别:${#}等同于$#,可以获取参数的数量;${#VAR}可以获得变量VAR所保存值的长度;${VAR#alt}执行的是替换操作(见下文)。

  • 默认值(:-=)
    FILEDIR=${1:-/tmp} :-的意思是如果指定的参数不存在或为空(这里的$1),则将运算符之后的内容(这里的/tmp)作为FILEDIR的值;否则使用已经设置好的值。注意,:-只返回值,但不赋值(本例中只是把/tmp这个值返回给FILEDDIR,但是不会给$1赋值为/tmp)。
    echo ${HOME:=/tmp} 该条命令会返回$HOME的当前值。如果$HOME为空或者没有设置,则会返回/tmp,并把/tmp赋值给$HOME。
    echo ${HOME=/tmp} 只有在变量不存在(从未设置或已经明确删除)时才进行赋值操作。
    cd ${BASE:="$(pwd)"} 用于替换的值不一定非得是字符串常量。它可以是更为复杂的shell表达式的结果,以及多种扩展。
    参数扩展:意味着可以使用其他变量,如${BASE:="$(pwd)"};
    波浪号扩展:意味着可以使用~bob这样的表达式,它会扩展成bob用户的主目录。可以通过${BASE:=~uid17}将默认值设置为用户UID7的主目录,但注意不要给~uid17加引号,因为波浪号扩展不会在引号中执行
    命令替换:将命令的输出结果作为变量的值,其语法为$(cmds)
    算数扩展:意味着可以使用$(())语法执行整数算术运算。例如echo ${BASE:=/home/uid$((ID+1))}

  • ${:?} 如果指定的参数不存在或为空,那么bash会输出错误消息并退出。
    FIELDIR=${1:?"Error. You must supply a scatch directory."}
    可以在错误信息中引用变量或执行其他命令。
    CVTTYPE=${3:?"Error. $USEAG $(rm $SCRATCHILE)"}
    会输出$USAGE的值,并执行rm操作。

  • :-+=?总结
    echo username=${username[运算符]$NEWNAME}
    “:=” username变量为空或未设置时,进行赋值操作;
    “=” 只有当username完全不存在时,才进行赋值操作。若username为空,返回空值。
    “:-” username变量为空或未设置时,返回NEWNAME的值,但不为username赋值
    “-” 只有当username完全不存在时,才返回NEWNAME的值,但不为username赋值
    “:?” 当username为空或未定义时,返回NEWNAME的值并退出
    “?” 只有当username未定义时,返回NEWNAME的值并退出
    “:+” 当username已定义其不为空时,返回NEWNAME的值但不为username赋值
    “+ ” 当username已定义时,返回NEWNAME的值但不为username赋值

    [root@web1 keys]# username=""
    [root@web1 keys]# echo $username
    
    [root@web1 keys]# echo ${username:+111}
    
    [root@web1 keys]# echo ${username+111}
    111
    [root@web1 keys]# username=a
    [root@web1 keys]# echo ${username:+111}
    111
    [root@web1 keys]# echo ${username+111}
    111
    
    #制作一个由逗号分隔的值列表,但不希望开头或结尾处出现逗号。
    LIST="${LIST}${LIST:+,}${NEWVAL}"  #可以简写为LIST="$LIST${LIST:+,}$NEWVAL"

    说明:如果LIST为空或不存在,则表达式的${LIST}${LIST:+,}不会产生任何值。这就意味着第一次循环过后,LIST中保存的只有NEWVAL的值。如果LIST不为空,那么${LIST:+,}部分会返回一个逗号“,”,此时的LIST的值=旧值,新值。

  • 字符串操作运算符

    运算符操作
    ${name:num1:num2}从字符串name的索引位置num1开始,返回长度为num2的子串
    ${#name}返回字符串的长度
    ${name#pattern}从字符串起始位置开始,删除匹配pattern的最短子串
    ${name##pattern}从字符串起始位置开始,删除匹配pattern的最长子串
    ${name%pattern}从字符串结束位置开始,删除匹配pattern的最短子串
    ${name%%pattern}从字符串结束位置开始,删除匹配pattern的最长子串
    ${name/pattern/string}将字符串中第一次出现的pattern替换为string
    ${name//pattern/string}将字符串中出现的所有的pattern替换为string

    例:
    1️⃣获取某个数的绝对值:${MYVAR#-} #将查找到的第一个减号删掉
    2️⃣剥离变量中的路径信息,只保留文件名:
    方法一:basename命令 FILE=$(basename $FULLPATHTOFILE)
    方法二:FILE=${basename##*/}
    区别:方法一使用的括号会生成一个子shell来执行basename命令。方法二使用的花括号只是shell变量替换语法的一种,不会生成子shell,也不会执行命令;它从字符串起始位置开始匹配,使用最长匹配(##)模式,*匹配任意字符,/仅代表字面含义。

    [root@web1 keys]# pwd
    /root/1panel/1panel/apps/halo/halo/data/keys
    [root@web1 keys]# file=$(pwd)
    [root@web1 keys]# echo $file
    /root/1panel/1panel/apps/halo/halo/data/keys
    [root@web1 keys]# echo ${file##*/}
    keys

    特别的,当变量的值以/结尾时,使用bash替换需要先处理最后的这个/,否则返回的将是空值。

    file=/usr/local/bin/
    echo ${file##*/}
                     #返回值为空,因为*/匹配了全路径
    #完整的处理方法
    file=${file%/}  #删除结尾处的/
    file=${file##*/} #删除最后一个/及之前的所有字符
    file=${file%.jpg} #如果存在,删除.jpg后缀
    #以上三条命令等效于 basename $file .jpg
    [root@web1 keys]# file=$(pwd)/id_rsa.pub
    [root@web1 keys]# echo $file
    /root/1panel/1panel/apps/halo/halo/data/keys/id_rsa.pub
    [root@web1 keys]# echo $(basename $file )
    id_rsa.pub
    [root@web1 keys]# echo $(basename $file .ppp)
    id_rsa.pub
    [root@web1 keys]# echo $(basename $file .pub)
    id_rsa
    [root@web1 keys]# echo $(basename $file rsa.pub)
    id_

    3️⃣删除变量中的文件名,保留目录部分:
    方法一:echo $(dirname $file)
    方法二:echo ${file%/*} #忽略了变量以/结尾的情况

  • 转换大小写
    变量FN中含有大小写字符串
    换为小写:${FN,,}
    换为大写:${FN^^}
    大小写互换:${FN~~}

    [root@web1 ~]# FN=aabbCCDD
    [root@web1 ~]# echo ${FN,,}
    aabbccdd
    [root@web1 ~]# echo ${FN^^}
    AABBCCDD
    [root@web1 ~]# echo ${FN~~}
    AABBccdd
    [root@web1 ~]#
    #只用一个操作符时,只转换第一个字符。
    [root@web1 ~]# fn=Aabb
    [root@web1 ~]# echo ${fn^}
    Aabb
    [root@web1 ~]# echo ${fn~}
    aabb
    [root@web1 ~]# echo ${fn,}
    aabb
    

    declare 命令在变量声明时也可以实现以上大小写变换,参数如下
    declare -u [变量名] #全部大写
    declare -l [变量名] #全部小写
    declare -c [变量名] # 仅首字母大写
    例:利用数组和大小写转换来给字符串中的每个单词的首字母都变为大写

    while read TXT
    do
    RA=($TXT)
    echo ${RA[@]^}

    说明: ($TXT)命令初始化数组。文本中分割单词的空白字符划分了数组元素。[@]语法一次性引用了全部的数组元素,^操作符将每个元素的首字母转换为大写。

0

评论

博主关闭了当前页面的评论