从shell眼中看世界–展开和引用

这篇博客的目的在于加深对于展开和引用的理解,阐释展开和引用之间联系。

‘ ‘ :强引用,其中的变量引用不会被替换为变量值,而保持原字符串
       ” “:弱引用,其中的变量引用会被替换为变量值
    如果之前对于’ ‘和” “的理解只停留在上述两句话的这个阶段,那么读完这篇博客相信你一定会有所收获。(本文会告诉你什么叫做一万句顶一句。)

    展开
        0.展开机制说明                  
        1.路径名展开                 *
        2.波浪线展开                 ~
        3.算术表达式展开           $(()) $[]
        4.花括号展开                 {}
        5.参数展开                    $
        6.命令替换                    $()   ` `

    0.展开机制说明
        echo是一个shell内部命令,作用是在标准输出中打印出它的文本参数。这里会使用echo命令来对所有展开进行说明,所以这一部分会非常容易理解。

        # echo this is a test
        this is a test


        echo将文本参数直接打印出来。

        # echo *
        aa addr.data anaconda-ks.cfg bin Checkos.sh hostch.sh hosts.bak hosts.BAK input ls-output.txt ls.txt Pics ping1.sh poem.txt shoplist.data test1.sh testuser.sh testz.sh tongku.sh


        如何工作:
        这里echo并没有直接打印,而是列出了当前工作目录下的所有文件(除了隐藏文件)及目录。这说明在echo命令执行前,shell把展开成了另外的东西。在对于通配符的学习中可以知道匹配任意长度的任意字符。当回车键被按下时,shell在命令被执行前自动展开当前工作目录下任何符合条件的文件名,所以echo命令所接收到的不是,而是*所展开成的结果。这就解释了echo * 执行结果。

        
    1.路径名展开
        在展开机制说明中提到的展开就是一种路径名展开。
        举例说明

        [root@localhost ~]# ls
        aa               Checkos.sh  input          ping1.sh       testuser.sh
        addr.data        hostch.sh   ls-output.txt  poem.txt       testz.sh
        anaconda-ks.cfg  hosts.bak   ls.txt         shoplist.data  tongku.sh
        bin              hosts.BAK   Pics           test1.sh

        /root目录中内容
        

        [root@localhost ~]# echo h*
        hostch.sh hosts.bak hosts.BAK


        h*展开为目录下以h开头的文件名
       

        [root@localhost ~]# echo *h
        Checkos.sh hostch.sh ping1.sh test1.sh testuser.sh testz.sh tongku.sh


        *h展开为目录下以h结尾的文件名

        [root@localhost ~]# echo [[:upper:]]*
        Checkos.sh Pics


        [[:upper:]]*展开为目录下以大写字母开头的文件名

        所谓展开就是shell对于命令行参数进行解释,改变其字面意义上的内容。(理解展开的关键)
        路径名展开把参数展开为符合匹配模式的内容。

    2.波浪线展开
        波浪线~是有特殊含义的。shell会对其进行特定解释。
        两种用法:
        ~后跟用户名,展开为指定用户的家目录。
        ~,不指定用户名,展开为当前用户的家目录。

        [root@localhost ~]# echo ~
        /root
        [root@localhost ~]# echo ~cold
        /home/cold


        
        波浪线展开:shell对~作特殊的解释说明。

    3.算术表达式展开
        shell允许算术表达式通过展开来执行。其格式$((expression))或者$[expression]
        操作符:+、-、*、/、%、**
        注意事项:
        算术表达式中空格并不重要,并且表达式可以嵌套。
        一对括号可以把子表达式括起来。由此可以简化嵌套。
        举例说明

        [root@localhost ~]# echo $((2+2))
        4
        [root@localhost ~]# echo $[2+2]
        4
        [root@localhost ~]# echo $(($((5**2))*3))
        75
        [root@localhost ~]# echo $(((5**2)*3))
        75


        算术表达式展开:执行算术表达式,并用结果替换之

    4.花括号展开
        相当有趣的一种展开。我将其理解为每个选项都选择一次。
        通过实例更容易说明其作用。

        [root@localhost ~]# echo Front-{A,B,C}-Back
        Front-A-Back Front-B-Back Front-C-Back


        选项用“,”隔开,ABC三个选项

        [root@localhost ~]# echo Number_{1..5}
        Number_1 Number_2 Number_3 Number_4 Number_5


        一系列整数

        [root@localhost ~]# echo {Z..A}
        Z Y X W V U T S R Q P O N M L K J I H G F E D C B A


        一系列倒序大写字母

        [root@localhost ~]# echo a{A{1,2},B{3,4}}b
        aA1b aA2b aB3b aB4b


        嵌套模式

        注意事项:
        {}中不能嵌入空白字符。下面是C前加入一个空白符后的执行结果。

        [root@localhost ~]# echo Front-{A,B, C}-Back
        Front-{A,B, C}-Back


        {}可以嵌套。

        这种展开最普遍的应用是,创建一系列的文件或目录列表。

        [root@localhost Pics]# mkdir {2015..2017}0{1..9} {2015..2017}{10..12}
        [root@localhost Pics]# ls
        201501  201505  201509  201601  201605  201609  201701  201705  201709
        201502  201506  201510  201602  201606  201610  201702  201706  201710
        201503  201507  201511  201603  201607  201611  201703  201707  201711
        201504  201508  201512  201604  201608  201612  201704  201708  201712


        看,相当的快捷方便。

    5.参数展开
        $变量名 将变量替换为变量值

        [root@localhost Pics]# echo $USER
        root


        USER系统定义的变量,变量值为当前用户名

        [root@localhost Pics]# x=10
        [root@localhost Pics]# echo $x
        10


        给x赋值为10,$x会被shell自动替换为10

    6.命令替换
        命令替换允许我们把一个命令的输出作为一个展开模式来使用。
        格式:$(command)   `command`

        [root@localhost ~]# which man
        /usr/bin/man
        [root@localhost ~]# ls -l `which man`
        -rwxr-xr-x. 1 root root 102736 Jun 10  2014 /usr/bin/man
        [root@localhost ~]# ls -l $(which man)
        -rwxr-xr-x. 1 root root 102736 Jun 10  2014 /usr/bin/man


        注意:命令的输出会被直接当成参数。如果命令输出不能直接作为下一条命令的参数,将不能正常执行。
        例如

        [root@localhost ~]# which cp
        alias cp='cp -i'
            /usr/bin/cp
        [root@localhost ~]# ls -l `which cp`
        ls: invalid option -- '''
        Try 'ls --help' for more information.


        which cp输出除文件路径还有其他内容,ls命令报错。

    引用
    shell有许多方式可以完成展开,现在是时候学习怎么来控制展开了。

    [root@localhost ~]# echo this is a    test
    this is a test


    shell从echo命令的参数列表中删除多余的空格。

    [root@localhost ~]# echo The total is $100.00
    The total is 00.00


    参数展开把$1 的值替换为一个空字符串,因为1是没有定义的变量。
    这里shell自作主张的对输入的字符串进行转换,有时这并不是我们所期望的。
    shell提供了引用机制,来有选择地禁止不需要的展开。
    

    1.双引号
        文本放在放在双引号之中,shell使用的特殊字符除$、\、`之外都会失去它们的特殊含义,被当做特殊字符对待。
        回想上面讲到的关于展开的内容,~波浪线展开,{}花括号展开,*等通配符的路径名展开,单词分割都被禁止。算术表达式展开,参数展开和命令替换仍然有效。
        
        注:什么是单词分割
        在默认情况下单词分割会在单词中寻找空格、制表符和换行符,并把它们看作单词之间的界定符。它们只作为分隔符使用。
        举例说明

        [root@localhost ~]# echo this is a    test
        this is a test


        这里多个空格只是作为分隔符使用,在上面这个例子中shell认为给出了四个参数,分别是this、is、a、test,将这四个参数传递给echo命令,因此执行结果中看不到多出的空格符的影响。
        [root@localhost ~]# echo “this is a    test”
        this is a    test
        在这个例子中this is a    test 文本被包含在””中,单词分割被禁止,内嵌的空格不再被当做界定符,而被作为参数的一部分。因此运行结果中输入的空格被保留了下来。

        这里还有一个关于单词分割的有趣例子,给出运行结果。

        [root@localhost ~]# echo $(cal)
        April 2017 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
        [root@localhost ~]# echo "$(cal)"
             April 2017     
        Su Mo Tu We Th Fr Sa
                           1
         2  3  4  5  6  7  8
         9 10 11 12 13 14 15
        16 17 18 19 20 21 22
        23 24 25 26 27 28 29
        30


    2.单引号
        单引号禁止包含文本的所有展开。
        举例说明

        [root@localhost ~]# echo text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER
        text /root/ls-output.txt /root/ls.txt /root/poem.txt a b cold 4 root


        所有展开都被允许。

        [root@localhost ~]# echo "text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER"
        text ~/*.txt {a,b} cold 4 root


        只有命令替换,算术表达式展开,参数展开被允许。

        [root@localhost ~]# echo 'text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER'
        text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER


        所有展开都被禁止。

    3.转义字符
        在双引号中使用转义字符,可以有选择地阻止展开。
 

        [root@localhost ~]# echo "The balance for $USER is:$5.00"
        The balance for root is:.00   


        两个$都被当做参数展开。

        [root@localhost ~]# echo "The balance for $USER is:\$5.00"
        The balance for root is:$5.00


        阻止了$5.00的展开,\$被显示为$。

        在双引号中反斜杠失去它的特殊含义,被当做普通字符。
        

    总结
    《The Linux Command Line》中是这样说明这一章节的:
     随着我们继续学习 shell,你会发现使用展开和引用的频率逐渐多起来,所以能够很好的理解他们的工作方式很有意义。事实上,可以这样说,他们是学习 shell 的最重要的主题。 如果没有准确地理解展开模 式,shell 总是神秘和混乱的源泉,并且 shell 潜在的能力也 浪费掉了。

原创文章,作者:maru,如若转载,请注明出处:http://www.178linux.com/73499

(0)
marumaru
上一篇 2017-04-16 22:13
下一篇 2017-04-16 22:23

相关推荐

  • N21沉舟11周作业

    1、请描述一次完整的http请求处理过程; (1) 建立或处理连接:接收请求或拒绝请求 (2) 接收请求: (3) 处理请求:对请求报文进行解析,并获取请求的资源及请求方法等相关信息 (4) 访问资源:获取请求报文中请求的资源 (5) 构建响应报文 (6) 发送响应报文 (7) 记录日志 …

    Linux干货 2016-09-26
  • 第六次上课作业

    1、三种权限rwx对文件和目录的不同意义 对文件 r:read  可读取此文件的实际内容,如读取文本文件的文字内容等 w: write  可以编辑,新增或修改该文件的内容 x:execute  该文件具有可以被系统执行的权限==>>针对二进制文件或脚本 X:针对目录会加上x权限…

    Linux干货 2016-08-04
  • 文件相关操作练习

    1、复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限: 2、编辑/etc/group文件,添加组hadoop: 3、手动编辑/etc/passwd文件新增一行,添加用户hadoop,其基本组ID为hadoop组的id号;其家目录为/home/hadoop: 4、复制/etc/sk…

    2017-11-17
  • 马哥教育网络班21期第8周课程练习

    1、请描述网桥、集线器、二层交换机、三层交换机、路由器的功能、使用场景与区别。 网桥也叫桥接器,是连接两个局域网的一种存储/转发设备,用来连接不同网段。 集线器称为“Hub”,主要功能是对接收到的信号进行再生整形放大,以扩大网络的传输距离,同时把所有节点集中在以它为中心的节点上。 二层交换机工作于OSI模型的第2层(数据链路层),可识别数据包中的MAC地址信…

    Linux干货 2016-09-19
  • shell脚本编程之变量详解

    什么是变量     变量是计算机内存的单元,其中存放的值可以改变。当Shell脚本需要保存一些信息时,如一个文件名或是一个数字,就把它存放在一个变量中。每个变量有一个名字,所以很容易引用它。 使用变量可以保存有用信息,使系统获知用户相关设置,变量也可以用于保存暂时信息。 变量:变量类型 作用:  &…

    Linux干货 2016-08-15
  • bind简单配置之子域、主从、视图

    [bind简单配置之子域、主从、视图] 标签:bind简单配置、子域、主从、视图 [逻辑拓扑结构图] ns.mylinux.com主机上面有两种网卡用来模拟两个不通的网段。 [子域配置]         域名内部还可以继续划分子域,进行分片管理。下面是正向子域授权的配置: &nb…

    Linux干货 2015-10-22

评论列表(1条)

  • renjin
    renjin 2017-04-21 09:40

    很明显,比上次写的博客都有一个大的提升,主要介绍了符号展开在linux shell中的用法,内容写的很详细,也很生动,排版还需要一个提升的过程,加油,加油