zoukankan      html  css  js  c++  java
  • Shell:八大扩展功能

    花括号

    在shell脚本中,可以使用括号对字符串进行扩展,我们可以在一对花括号中包含一组以分号分隔的字符串或者字符串序列组成一个字符串扩展,注意最终输出结果以空格分隔,使用该扩展花括号不可以被引号引用,花括号的数量必须是偶数个。

    [root@localhost ~]# echo {1,5} #对字符串进行扩展
    1 5
    [root@localhost ~]# echo {hello,world} #对字符串进行扩展
    hello world
    [root@localhost ~]# echo {a..z} #对字符串序列进行扩展
    a b c d e f g h i j k l m n o p q r s t u v w x y z
    #字符串后面可以跟一个步长整数,默认为1或-1
    [root@localhost ~]# echo {a..z..2}
    a c e g i k m o q s u w y
    [root@localhost ~]# echo {a..z..3}
    a d g j m p s v y
    [root@localhost ~]# echo {1..9..3}
    1 4 7
    [root@localhost ~]# echo {1..9..2}
    1 3 5 7 9
    [root@localhost ~]# echo "{a..z}" #花括号扩展不能使用引号
    {a..z}
    [root@localhost ~]# echo t{i,o}p #花括号前后都可以添加可选字符串
    tip top
    [root@localhost ~]# echo t{o,e{a,m}}p #花括号支持嵌套
    top teap temp
    #花括号批量操作
    [root@localhost ~]# mkdir -p t{o,e{a,m}}p
    [root@localhost ~]# touch t{o,e{a,m}}p/{a,b,c,d}e.txt
    
    

    波浪号

    波浪号在shell脚本中默认代表当前用户家目录

    [root@localhost /]# echo ~ #显示当前用户的家目录
    /root
    [root@localhost /]# echo ~/elk
    /root/elk
    [root@localhost /]# echo ~elk #显示特定用户的家目录,该用户必须存在
    /home/elk
    [root@localhost /]# echo ~+ #显示当前工作目录
    /
    [root@localhost /]# echo ~- #显示前一个工作目录
    /root
    

    变量替换

    在shell脚本中我们会使用$对变量进行扩展替换,变量字符可以放到花括号中,这样可以防止需要扩展的变量字符与其他不需要扩展的字符混淆,如果$后面是位置变量且多余一个数字,必须使用{}

    [root@localhost /]# a="hello word"
    [root@localhost /]# echo $a
    hello word
    [root@localhost /]# echo ${a}
    hello word
    [root@localhost /]# b=a
    [root@localhost /]# echo ${b} #直接返回变量的值
    a
    [root@localhost /]# echo ${!b} #间接引用a变量的值
    hello word
    [root@localhost /]# c=b
    [root@localhost /]# echo ${!c} #尽可以实现一层简介引用
    a
    

    变量替换操作还可以测试变量是否存在及是否为空,若变量不存在或为空,则可以为变量设置一个默认值。

    shell脚本支持多种形式的变量测试与替换功能,如下表所示:

    语法格式 功能描述
    ${变量:-关键字} 如果变量未定义或为空,则返回关键字,否则返回变量值
    ${变量:=关键字} 如果变量未定义或为空,则将关键字赋值给变量,并返回结果,否则直接返回变量值
    ${变量:?关键字} 如果变量未定义或为空,则通过标准错误显示包含关键字的错误信息,否则返回变量值
    ${变量:+关键字} 如果变量未定义或为空,则直接返回空,否则返回关键字

    image-20210714231633253

    此外,变量替换还有非常实用的字符串切割与掐头去尾功能

    偏移量起始值为0

    语法格式 功能描述
    ${变量:偏移量} 从变量的偏移量位置开始,切割截取变量的值到结尾
    ${变量:偏移量:长度} 从变量的偏移量位置开始,切割截取特定长度的变量值
    ${变量#关键字} 用关键字对变量进行模式匹配,从左到右删除匹配到的内容,关键字可以用*表示,使用#匹配时为最短匹配
    ${变量##关键字} 用关键字对变量进行模式匹配,从左到右删除匹配到的内容,关键字可以用*表示,使用##匹配时为最长匹配
    ${变量%关键字} 用关键字对变量进行模式匹配,从右到左删除匹配到的内容,关键字可以用*表示,使用%匹配时为最短匹配
    ${变量%%关键字} 用关键字对变量进行模式匹配,从右到左删除匹配到的内容,关键字可以用*表示,使用%%匹配时为最长匹配

    这几种变量替换方式,都不会改变原变量的值

    演示:

    [root@localhost /]# home="hello word linux java spring"
    [root@localhost /]# echo ${home:2}
    llo word linux java spring
    [root@localhost /]# echo ${home:2:5}
    llo w
    [root@localhost /]# echo ${home#he}
    llo word linux java spring
    [root@localhost /]# echo ${home#*ja}
    va spring
    [root@localhost /]# echo ${home##*r}
    ing
    [root@localhost /]# echo ${home%ing}
    hello word linux java spr
    [root@localhost /]# echo ${home%i*}
    hello word linux java spr
    [root@localhost /]# echo ${home%%i*}
    hello word l
    

    变量内容的统计与替换:

    语法格式 功能描述
    ${!前缀字符*} 查找以指定字符开头的变量名称,变量名之间使用IFS分隔
    ${!前缀字符@} 查找已制定字符开头的变量名称,@在引号中将被扩展为独立的单词
    ${!数组名称[*]]} 列出数组中所有下标,*在引号中被扩展为一个整体
    ${!数组名称[@]]} 列出数组中所有下标,@在引号中被扩展为独立的单词
    ${#变量} 统计变量的长度,变量可以是数组
    ${变量/旧字符串/新字符串} 将变量中的旧字符串替换为新字符串,仅替换第一个
    ${变量//旧字符串/新字符串} 将变量中的旧字符串替换为新字符串,替换所有
    ${变量^匹配字符} 将变量中的小写替换为大写,仅替换第一个
    ${变量^^匹配字符} 将变量中的小写替换为大写,替换所有
    ${变量,匹配字符} 将变量中的大写替换为小写,仅替换第一个
    ${变量,,匹配字符} 将变量中的大写替换为小写,替换所有

    命令替换

    #我们可以通过$(命令)或`命令`方式实现替换
    
    [root@localhost /]# echo -e "$(date +%Y-%m-%d;uptime)"
    2021-07-14
     23:47:56 up 29 days,  4:12,  1 user,  load average: 0.36, 0.18, 0.14
    [root@localhost /]# echo "系统登录人数:$(who | wc -l)"
    系统登录人数:1
    [root@localhost /]# echo "系统登录人数:`who | wc -l`"
    系统登录人数:1
    

    算数替换

    通过算数替换扩展可以进行算数计算并返回计算结果,算数替换扩展的格式为$(()),也可使用$[]的方式,算数扩展支持嵌套

    [root@localhost /]# echo $((i++))
    1
    [root@localhost /]# echo $((++i))
    3
    [root@localhost /]# echo $((--i))
    2
    [root@localhost /]# echo $((18%5)) #取余
    3
    [root@localhost /]# echo $((2**3)) #幂运算
    8
    [root@localhost /]# echo $((2>3))
    0
    [root@localhost /]# echo $((2<3))
    1
    [root@localhost /]# echo $((2!=3))
    1
    

    进程替换

    进程替换将进程的返回结果通过命名管道的方式传递给另一个进程

    语法格式为:<(命令)或者>(命令)

    一旦使用了进程替换功能,系统将会在/dev/fd目录下创建文件描述符文件,通过该文件描述符将进程的输出结果传递给其他进程

    linux系统中可以使用管道将前一个命令输出重定向到文件,但是一旦使用了重定向输出到文件,输出结果无法在屏幕上显示

    [root@localhost /]# ls /etc/*.conf > ~/conf.log
    [root@localhost /]# cat ~/conf.log
    /etc/asound.conf
    /etc/chrony.conf
    /etc/dracut.conf
    ...后续内容省略...
    

    使用tee命令既可以重定向到文件,又可以在屏幕上显示输出结果

    [root@localhost /]# ls /etc/*.conf |  tee ~/conf.log
    /etc/asound.conf
    /etc/chrony.conf
    /etc/dracut.conf
    ...后续内容省略...
    [root@localhost /]# cat ~/conf.log
    /etc/asound.conf
    /etc/chrony.conf
    /etc/dracut.conf
    ...后续内容省略...
    

    单词切割

    单词切割又叫做分词,shell使用IFS变量进行分词处理。如果没有自定义IFS变量,默认为空格、Tab制表符、换行符

    [root@localhost ~]# read -p "输入:" x y z
    输入:1 2 3
    [root@localhost ~]# echo $x
    1
    [root@localhost ~]# echo $y
    2
    [root@localhost ~]# echo $z
    3
    #自定义IFS变量的值
    [root@localhost ~]# IFS=$',' read -p "输入:" x y z
    输入:4,5,6
    [root@localhost ~]# echo $x
    4
    [root@localhost ~]# echo $y
    5
    [root@localhost ~]# echo $z
    6
    

    路径替换

    除非使用set -f禁用路径替换,否则bash会在路径和文件名中搜索*、?和[符号,如果找到了这些符号则进行模式匹配的替换。

    使用shopt命令时开启了nocaseglob选项,则bash的进行模式匹配时不区分大小写,默认区分大小写。

    此外还可以开启extglob选项,让bash支持扩展通配符。

    shopt命令-s选项可以开启特定的Shell属性,-u选项可以关闭特定的Shell属性

    [root@localhost shopt]# touch {a,A,b,B}.txt
    [root@localhost shopt]#
    [root@localhost shopt]# ls a.txt
    a.txt
    [root@localhost shopt]# shopt -s nocaseglob
    [root@localhost shopt]# shopt nocaseglob
    nocaseglob      on
    [root@localhost shopt]# ls B*
    b.txt  B.txt
    [root@localhost shopt]# ls a*
    a.txt  A.txt
    [root@localhost shopt]# shopt -u nocaseglob
    [root@localhost shopt]# ls a*
    a.txt
    [root@localhost shopt]# shopt -s extglob
    [root@localhost shopt]# ls !(a.txt|b.txt)
    A.txt  B.txt
    [root@localhost shopt]# shopt -u extglob
    [root@localhost shopt]# ls !(a.txt|b.txt)
    -bash: !: event not found
    

    basenamedirname:

    basename:可以获取一个路径中的文件名

    dirname:仅保留路径,删除文件名

    [root@localhost shopt]# basename /a/b/c/d.txt
    d.txt
    [root@localhost shopt]# dirname /a/b/c/d.txt
    /a/b/c
    
  • 相关阅读:
    [EffectiveC++]item22:Declare data members private
    垃圾人定律
    [EffectiveC++]item17:以独立语句将newed对象置入智能指针
    [EffectiveC++]item15:Provide access to raw resources in resource-managing class
    C++ 中operator用法:隐式类型转换
    [EffectiveC++]item13:Use objects to manage resources(RAII)
    为什么拷贝构造函数的参数必须是引用?
    SPF邮件服务器
    raspberry
    bash
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/15013602.html
Copyright © 2011-2022 走看看