`
姜太公
  • 浏览: 74891 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

Shell命令中的扩展和替换

阅读更多

Shell的强大,很大程度上得益于对命令行做了额外的处理,你可以再命令中嵌入其他命令,在参数中嵌入其他命令,或者嵌入变量,插入路径通配符,插入表达式,Shell都能帮你处理的很好,就因为Shell能做这些,所以Shell才如此强大。

 

废话少说,直接开始。

 

首先还是要啰嗦两句,说说Shell处理命令的过程,网上有篇文章写的很不错,很详细,不过我忘记在那儿了,有兴趣的同学可以找找看,用google!我只想说一句:弄清楚Shell处理命令的过程很重要。

 

简单的说下shell处理命令的过程是:

1.先按<tab> <newline> <space> ( ) < > ; l &把命令分割成一个个的token

2.检查第一个token是不是一个开放的关键字,如for if {等,如果是,说明这是一个复合命令,shell会在内部对关键字进行处理,并重复这一步骤。

3.按别名列表检查每个命令的第一个关键字是不是一个别名,如果是别名,则用其别名定义替换,然后回退到第一步。

4.执行花括号{}扩展

5.执行波浪号~扩展

6.执行变量扩展

7.执行命令替换

8.执行算术表达式计算

9.把生成的新命令按IFS分割成token

10.执行路径扩展

11.按优先级查找命令,先从内置,再从PATH。

12.设定好重定向等,执行命令

 

过程大致是这样,这里写的很错略,只是为了帮助更好的了解后文。这里要说的就是4,5,6,7,8,10

 

在Shell中,有六种扩展:花括号、波浪号、变量扩展、命令替换、算术扩展和路径扩展。

 

花括号扩展:

简单点说就是给一组字符串加上相同的前缀和后缀,生成一组新的字符串。前缀和后缀都可以为空。

[jjz@localhost ~]$ echo a{b,c}d
abd acd
[jjz@localhost ~]$ echo a{b,c}
ab ac

可以使用一个范围,只支持数字和字母。

[jjz@localhost ~]$ echo a{1..10}
a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
[jjz@localhost ~]$ echo a{a..f}
aa ab ac ad ae af

 

花括号还可以嵌套,逐层有序的进行处理。

[jjz@localhost ~]$ echo a{{1,2},{b,c}}
a1 a2 ab ac

 可以认为先生成a{1,2,b,c},然后生成a1 a2 ab ac

要注意的地方:

  1. 花括号里只有字面量,不要试图使用变量,花括号不支持,比如
    [jjz@localhost ~]$ a=1
    [jjz@localhost ~]$ echo {$a..10}
    {1..10}
    
     并没有生成1 2 3 4 5 6 7 8 9 10。对大括号扩展来说,生成的结果是{$a..10} ,那为什么我们看到的会是{1..10}呢?这就和Shell的命令处理顺序有关了,我们再看看Shell的命令处理顺序,花括号扩展是在第四步,到了第六步,会执行变量扩展,这时候相当于 命令
    echo {$a..10}
     $a被替换成了1,当然输出的就是{1..10}了。
  2. 花括号里至少要有一个逗号,也就是至少要有两项
  3. 两项之间不能有空格,也就是逗号前后不能有空格,否则不进行花括号扩展。

波浪号扩展

波浪号扩展就是对~进行处理。一般情况下,我们认为~代表了自己的主目录,其实事情并非这么简单。进行波浪号替换的条件是很苛刻的。

首先,进行波浪号扩展的前提是波浪号必须位于一个token的开头,简单的说,~前面应该是空格。

然后,shell会分析波浪号之后,第一个/或:之前的未被引号括起来的字符串(如果没有/,那就取波浪号之后的所有字符),这个字符串叫做"波浪号前缀(tilde-prefix)"(注意,所谓波浪号前缀其实是出现在波浪号后面的),波浪号前缀的取值和对应的处理方式是:

  1. 如果波浪号前缀是个有效用户名,则波浪号和波浪号前缀一起替换成这个用户的主目录
  2. 如果波浪号前缀为空,则尝试把波浪号替换成HOME,如果HOME没有被设置,则将波浪号替换成当前用户主目录。
  3. 如果波浪号前缀是+,则~+被替换成当前工作目录(PWD)
  4. 如果波浪号前缀是-,则~-被替换成上一个工作目录(OLDPWD)
  5. 如果波浪号前缀是个数字n,则把~n替换成目录堆栈(用dirs命令可以查看目录堆栈)的第n个元素(这个似乎没什么用)

 

[jjz@localhost ~]$ echo ~
/home/jjz
[jjz@localhost ~]$ echo /~
/~                                         波浪号不是在token的开头,不进行扩展
[jjz@localhost ~]$ echo ~root
/root
[jjz@localhost ~]$ echo ~root/
/root/
[jjz@localhost ~]$ echo ~+
/home/jjz                               替换成 当前目录
[jjz@localhost ~]$ echo ~-
~-                                          替换成上一个目录,因为我没用过cd,上一个目录OLDPWD没有设置,所谓替换失败,原样输出
[jjz@localhost ~]$ cd project
[jjz@localhost project]$ echo ~-        这个好了
/home/jjz
[jjz@localhost project]$ 

 

变量扩展

这个大家最熟悉了,$foo!$真是个好东西,变量扩展,命令替换,算术扩展都离不了它(当然还能买东西)。一般情况下我们习惯使用$var,其实正规的格式是${var}。前一种形式更简便,后一种更强大,很多时候必须用后一种形式才行。

 

先说说间接引用,这东西很像C语言里的指针。

${!var},就是左花括号后面紧跟一个感叹号。bash会把变量的值作为新的变量再求值。

[jjz@localhost project]$ a=b
[jjz@localhost project]$ b=1
[jjz@localhost project]$ echo ${!a}
1

 其他的操作还是列个表出来,看上去可能更清晰

 

形式 意义
${var:-word} 如果变量var已被设置且非空,则代入它的值,否则带入word
${var:=word} 如果变量var已被设置且空,就带入它的值,否则将var设为word并带入var,位置参量不能用这种方式赋值。
${var:+word} 如果var已被设置且值非空,带入word;否则什么都不带入(带入空)
${var:?word} 如果var已被设置且值非空,就带入它的值,否则打印word并退出shell。省略word会输出:parameter null or not set
注意:上面word可以是一个变量,使用$word的形式引用其值
${var:offset} 获取var中offset开始的字串
${var:offset:length} 获取var中offset开始长为length的字串。
注意:上面的offset和length可以使变量,使用$offset,$length引用其值
${#var} 替换为变量中字符个数,如果var是* ,@或数组,长度则是位置参量的个数。
${var%pattern} 把字符串尾部与模式进行最小匹配,并删除匹配到的部分。
${var%%pattern} 把字符串尾部与模式进行最大匹配,并删除匹配到的部分。
${var#pattern} 把字符串头部与模式进行最小匹配,并删除匹配到的部分。
${var##pattern} 把字符串头部与模式进行最大匹配,并删除匹配到的部分
${var/pattern/string} 使用string替换pattern的最大匹配部分。如果pattern以/开头则进行全部替换,否则只替换第一个匹配的位置。如果pattern以#开始,则起始部分必须匹配,如果以%开始则结尾部分必须匹配

注意:

上面的pattern可以使变量,使用$pattern引用其值。

如果var是*、@或数组且以下标为*或@的形式出现,则对其中每一个元素都进行匹配操作。

 

命令替换

 

用命令的输出来替换命令本身。有两种形式$(cmd)和`cmd`,推荐前一种形式,后一种形式是old-style了。这个没什么好说的,很简单。


算术扩展

 

用算术表达式的值替换算术表达式本身。格式$((expr))。expr是个表达式,如4+3。理解起来比较简单。不过关于expression,bash有自己特定的支持,某些运算它是做不了的。

[jjz@localhost project]$ echo $((9+2))
11
[jjz@localhost project]$ b=2
[jjz@localhost project]$ echo $((4+b))
6
[jjz@localhost project]$ 

 

路径扩展

shell扫描每个标记看看是否有*,?和[],这三个就是进行路径扩展的。如果某个标记里出现了三者中的一个或几个,这个标记就被认为是一个模式,shell会对当前目录下的文件列表按文件名排序并逐一与此模式进行比较,如果有匹配这个模式的文件,shell用所有能匹配这个模式的文件名列表替换这个模式。如果没有能匹配这个模式的文件,shell原样保留该模式。当然,shell提供了很多选项,定制匹配成功和失败的处理,还可以选择使用高级的正则表达式,这里不进行讨论,只说说shell的默认情况。此处的三个特殊字符也都比较简单*匹配0到多个字符,?匹配一个字符,[]匹配某个区间里一个字符。

分享到:
评论
2 楼 celaai 2012-10-25  
写的真好... 1024
1 楼 loamy 2009-05-18  
不错,学习ing

相关推荐

    Shell脚本学习教程PDF版

    函数和数组也是Shell脚本中不可或缺的部分。函数能实现代码复用,提高效率,而数组则允许我们存储一组相关的值,方便处理。在bash中,数组支持多维,这对于处理复杂数据结构尤其有用。 此外,Shell脚本还涉及到文件...

    Linux Shell脚本编程--sed命令详解.zip_shell sed_命令介绍_脚本 shell

    在Linux系统中,Shell脚本编程是日常自动化任务和系统管理的重要工具,而`sed`(流编辑器,Stream Editor)则是Shell脚本中的一个强大工具。本文将深入讲解`sed`命令的基本概念、功能以及在Shell脚本中的具体应用。 ...

    shell脚本编程02

    在shell脚本中,变量替换允许我们动态地修改和操作变量的值。这包括使用`$`符号来引用变量,以及使用各种替换运算符,如`${variable#pattern}`(删除匹配的最左边模式)和`${variable##pattern}`(删除所有匹配的最...

    Shell脚本专家指南

    2. 正则表达式:学习如何在脚本中使用正则表达式进行字符串匹配和替换。 3. 条件测试:掌握test命令或[ ]括号用于各种条件检查。 4. 脚本调试:学习set命令和trap命令用于调试和异常处理。 四、Shell脚本实战 1. ...

    高级Shell脚本编程.zip

    Shell脚本编程是Linux/Unix系统中的重要技能,它是一种用于自动化任务、管理系统和实现批处理操作的脚本语言。在Linux环境中,Bash(Bourne-Again SHell)是最常用的Shell,它扩展了原始的Bourne Shell功能,并且在...

    linux shell 脚本入门

    Linux Shell脚本是Linux系统中用于自动化任务的强大工具,它基于Bash或其他Shell解释器,允许用户编写一系列命令,以实现批处理、任务调度或任何需要自动化的工作流程。本PDF文档"shell-script-entry.pdf"提供了18页...

    shell脚本传参、嵌入式命令

    `set`命令在shell脚本中用于设置或改变shell的选项和环境。它也可以用来传递额外的参数,尤其是在脚本内部需要动态调整参数的情况下。例如: ```bash #!/bin/bash set -- "new_arg1" "new_arg2" # 添加新的参数 ...

    shell中变量替换.docx

    在Shell编程中,变量替换和测试是至关...以上就是Shell中关于变量替换、测试、字符串处理以及一些核心命令的基本知识,它们构成了Shell脚本编程的基础。理解并熟练掌握这些概念,将有助于编写高效和灵活的Shell脚本。

    Shell脚本专家指南.sed与awk第二版.shell十三问

    此外,指南可能还会讨论高级特性,如数组、shell别名、shell函数以及bash的扩展特性,帮助用户提升编写复杂脚本的能力。 接下来是"sed与awk第二版",sed(流编辑器)和awk(数据处理语言)是Linux文本处理的两个...

    Linux主要shell命令、sed、awk使用详解

    Linux 主要shell命令、sed、awk使用详解 Linux 主要shell命令详解 shell 是用户和 Linux 操作系统之间的接口。Linux 中有多种 shell,其中缺省使用的是 Bash。本章讲述了 shell 的工作原理,shell 的种类,shell ...

    shell执行mysql脚本

    在IT行业中,shell脚本和MySQL数据库是两个非常重要的工具。Shell脚本是Linux或Unix系统中的编程语言,用于自动化日常任务,而MySQL则是一种广泛使用的开源关系型数据库管理系统。当我们需要在Linux环境下批量处理...

    linuxShell脚本编写实验7报告.pdf

    5. **命令扩展功能**:Shell提供了命令扩展功能,如命令替换和参数扩展。例如,`openssl rand -base64 7`生成一个随机的base64编码字符串,可用于创建用户密码。`echo "user-1: $(openssl rand -base64 7)" &gt; /root/...

    ShellEd(shell脚本编辑器)

    2. **自动完成与代码补全**:在编写shell脚本时,ShellEd提供了智能代码补全功能,能够根据上下文自动推荐命令、参数和变量,极大地提升了编码速度和准确性。 3. **调试支持**:作为一个专业的shell脚本编辑器,...

    递归替换.c和.h文件中TAB键为4个空格的shell脚本,执行非常方便

    递归替换.c和.h文件中TAB键为4个空格的shell脚本,如果需要扩展,可以修改一下shell脚本,加上对应的类型,比如cpp或hpp。操作步骤非常简单: 将压缩包在linux下解压,把replaceTAB.sh上传到需要操作的目录,注意...

    高级Shell脚本编程指南

    **高级Shell脚本编程指南** 在信息技术领域,Shell脚本是一种强大的工具,它允许用户通过命令行接口自动化执行一系列操作。对于系统管理员、开发者以及任何需要处理日常任务的人来说,掌握高级Shell脚本编程技巧是...

    shell命令shell命令(资料包)

    Shell命令是与Linux操作系统交互的主要工具,它提供了一种高效的方式来进行自动化任务、管理文件和系统操作。本资料包着重于Linux Shell编程,旨在帮助用户深入理解和掌握这一核心技术。 1. **Shell介绍** Linux ...

Global site tag (gtag.js) - Google Analytics