本文主要讲bash脚本中容易出错和很少用但是用起来有意想不到效果的部分。

循环:

正常的for循环:

  1. for i in a b c 1 2 3; do
  2. echo "$i"
  3. done

数字序列循环:

  1. for i in `seq `; do
  2. echo "$i"
  3. done

其中的 `seq ` 也可以换成 {..}

{开始..结尾}的这种形式可以表示连续的数列,可以从小到大也可以从大到小,但是可惜不像python的range()那样可以指定间隔量

C语言风格的for循环:

  1. for (( i=; i<; i++ )); do
  2. echo "$i"
  3. done

for循环迭代文本

for循环会使用空格、换行符、制表符分割文本,依次迭代,如:

  1. a="ab cd
  2. ef"
  3.  
  4. for i in $a; do
  5. echo "$i"
  6. done

输出结果:

  1. ab
  2. cd
  3. ef

shell分割文本其实是以一个全局变量$IFS为依据的,默认情况下IFS=$'\n\t '(即换行符、制表符、空格),可以通过修改IFS的值来改变迭代文本的分割方式。

请注意上面的$a如果加引号括起来的话,会把它当成一个整体,不会切割迭代。

数学计算

双括号“(())”还可以用于数学计算:

  1. (( a=+ ))
  2. echo $a
  3. #

在双括号中,变量并不需要用$符号来引用,英文单词天然是变量。

变量:

间接引用:

  1. a=b
  2. b=
  3. echo ${!a}
  4. #

效果等同于 eval echo \$$a

特殊字符转义

包含特殊字符的字符串:

  1. echo "ab\ncd"

上列命令会输出字符ab+换行+cd,但是实际上字符串"ab\ncd"中并不包含“换行”这个字符,输出的换行只是echo命令解析的结果。

  1. # a="ab\ncd"
  2. # echo "length of var a is ${#a}"
  3.  
  4. length of var a is

通过${#var}的形式可以得到一个字符串的长度,上面示例可以看出来,字符串"ab\ncd"的长度是6而不是预期的5。

那么能否将不可打印的字符赋值给变量呢?答案是肯定的:

  1. # a=$'\x61\n\x62'
  2. # echo "$a"
  3. a
  4. b

请注意一定用的是单引号“'”,用双引号括起来是不起转义作用的。

字符串操作

变量值字符截取:

  1. a="abcdefg"
  2. echo ${a:}
  3. # cdefg
  4. echo ${a::}
  5. # cde

变量值字符删除:(#为从头部开始匹配,%为从尾部匹配,支持通配符“?*”)

  1. a="abdcdefgh"
  2. echo ${a#*d} # 删除字符串头部匹配“*d”的部分,通配符*代表匹配任意多个字符,一个#号代表通配符“*”保守匹配
  3. # cdefgh
  4. echo ${a##*d} # 两个#号表示贪婪匹配
  5. # efgh
  6. echo ${a%d*} # 同上,两个%时代表贪婪匹配
  7. # abdc
  1. a=b
  2. b="abcdefg"
  3. echo "${!a#abc}"
  4. # defg

可以同时支持间接引用和字符删除

变量赋值安全

用于赋值前检查是否已经定义或赋值。

  1. unset a
  2. unset b
  3. b="" # a没有定义,b定义了但是空值
  4. echo ${a-}  # 如果没定义,则表达式采用默认值789
  5. #
  6. echo ${a:-} # 如果没定义或是空值,则表达式采用默认值789
  7. #
  8. echo ${b-} # 如果没定义,则表达式采用默认值789,b定义了
  9. #
  10. echo ${b:-} # 如果没定义或是空值,则表达式采用默认值789
  11. #
  12. echo $a # 原变量并没有被赋值
  13. #
  14. echo $b # 原变量并没有被赋值
  15. #
  16. b=
  17. echo ${b-} # 如果变量已经被赋值,则不改变原有值
  18. #
  1. unset a
  2. echo ${a=} # 如果a没定义,则表达式采用默认值,并给a赋值
  3. #
  4. echo $a
  5. # # a已经被赋值了
  6. a=""
  7. echo ${a=}
  8. #
  9. echo ${a:=} # 加冒号:的作用和之前一样
  10. #
  11. echo $a
  12. #

前面讲了用“-”和“=”的,还有一种用“+”的,用于当变量已经被赋值的情况下采用默认值,举一反三,不赘述了。

位置变量

$0是文件名,$#代表参数个数,$1,$2等等表示执行该脚本或函数后面跟的位置参数,$1代表第一个参数,依次类推,需要注意的是,第9个以后的参数应该这么表示:

  1. ${}

这表示第10个参数,必须用花括号括起来,否则就变成第1个变量后面加个字符“0”了。因为这个有的人以为第9个以后的位置变量就不可用了,是错的。

$@和$*都表示所有的变量,但是区别是前者将每个作为一个字符串,是多个字符串的结合,而后者将所有变量组合成一个字符串,用空格分隔。

这样不同会在for循环里面造成使用的区别,在for循环里面,如果加上引号 for i in "$@" 和 for i in "$*" 是不同的,前者还是会依次把参数代入循环,而后者会吧所有参数作为字符串一次性代入:

  1. echo '
  2. for i in "$@"; do
  3. echo "$i"
  4. done
  5. for i in "$*"; do
  6. echo "$i"
  7. done
  8. ' > myscript.sh
  9. chmod myscript.sh
  10. ./myscript.sh abc def

结果是:

  1. abc
  2.  
  3. def
  4. abc def

那么$@加引号和不加引号有区别么?

大部分情况下结果看起来是一样的,但会在某些情况下造成麻烦,因为for循环会用换行符“\n”和空格来拆分变量,所以如果调用脚本所带的参数中带有空格或者换行符,不加引号的时候会把这个参数拆开了依次代入,而加了引号就可以避免这种情况。

  1. echo '
  2. for i in "$@"; do
  3. echo "$i"
  4. done
  5. for i in $@ ; do
  6. echo "$i"
  7. done
  8. ' > myscript.sh
  9. chmod myscript.sh
  10. ./myscript.sh abc "123 def"

结果是:

  1. abc
  2. def
  3. abc
  4.  
  5. def

for循环使用数组

将数组的值依次代入循环,可以用${arr[@}和${arr[*]}这两种方法,区别和加引号的区别同上面位置参数的使用相同。

字符串比较

shell的字符串匹配通常是这样的:

  1. [ "abc" = "abc" ]
  2. echo $?
  3. #

$? 这个变量代表上条命令的返回码。若字符串相同则返回0,否则返回1。除了全匹配外,通过双方括号“[[]]”还可以用正则表达式匹配

  1. [[ "abc234def" =~ ^abc[-]{}[a-z]+$ ]]
  2. echo $?
  3. #

注意这里正则表达式不能用引号括起来,而且只支持基本的正则,不支持如“\b \S”之类的扩展。

另单方括号‘[ ]’和双方括号‘[[ ]]’的区别,单括号等同于bash内置test命令,双方括号不是命令,是bash关键字。

原文地址:http://www.cnblogs.com/foxgab/p/6901782.html

如果觉得本文对您有帮助,请扫描后面的二维码给予捐赠,您的支持是作者继续写出更好文章的动力!

linux shell编程-bash的奇技淫巧的更多相关文章

  1. linux —— shell 编程(文本处理)

    导读 本文为博文linux —— shell 编程(整体框架与基础笔记)的第4小点的拓展.(本文所有语句的测试均在 Ubuntu 16.04 LTS 上进行) 目录 基本文本处理 流编辑器sed aw ...

  2. linux —— shell 编程(编程语法)

    导读 本文为博文linux —— shell 编程(整体框架与基础笔记)的第4小点的拓展.(本文所有语句的测试均在 Ubuntu 16.04 LTS 上进行) 目录 再识变量 函数 条件语句 循环语句 ...

  3. linux shell编程总结

    linux shell编程总结 本周学习了unix/linux shell编程,参考的是<LINUX与UNIX Shell 编程指南>,David Tansley著:徐焱,张春萌等译,由机 ...

  4. Linux Shell编程参考大全

    本文记录Linux Shell编程中常用基本知识,方便快速入门以及查询使用. 本文主要分为以下几个部分: 一.Shell中的变量 任何编程语言中,有关变量的定义,作用范围,赋值等都是最最基础的知识. ...

  5. linux shell 编程参考

    #!/bin/bash my_fun() { echo "$#" } echo 'the number of parameter in "$@" is '$(m ...

  6. 一文学完Linux Shell编程,比书都好懂

    一. Shell 编程 1. 简介 Shell 是一个用 C 语言编写的程序,通过 Shell 用户可以访问操作系统内核服务. Shell 既是一种命令语言,又是一种程序设计语言. Shell scr ...

  7. 前端学习 linux —— shell 编程

    前端学习 linux - shell 编程 shell 原意是"外壳",与 kernel(内核)相对应,比喻内核外的一层,是用户和内核沟通的桥梁.shell 有很多种,国内通常使用 ...

  8. Linux Shell编程中的几个特殊符号命令 & 、&& 、 ||

    https://blog.csdn.net/hack8/article/details/39672145 Linux Shell编程中的几个特殊符号命令 & .&& . || ...

  9. Linux Shell编程与编辑器使用详解

    <Linux Shell编程与编辑器使用详解> 基本信息 作者: 刘丽霞 杨宇 出版社:电子工业出版社 ISBN:9787121207174 上架时间:2013-7-22 出版日期:201 ...

随机推荐

  1. Java多线程中线程间的通信

    一.使用while方式来实现线程之间的通信 package com.ietree.multithread.sync; import java.util.ArrayList; import java.u ...

  2. margin重叠

    margin重叠也就是我们常说的CSS 外边距合并,W3C给出如下定义: 外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距. 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者 ...

  3. springboot(十):邮件服务

    springboot仍然在狂速发展,才五个多月没有关注,现在看官网已经到1.5.3.RELEASE版本了.准备慢慢在写写springboot相关的文章,本篇文章使用springboot最新版本1.5. ...

  4. Mac电脑使用Android Studio进行真机调试

    第一步: 为mac电脑配置 adb 命令的环境变量,分为2小步 1.找到 Android Studio 为你安装的 SDK : 打开电脑中 Android studio 的工具的软件,在启动 Andr ...

  5. 博弈论(Game Theory) - 02 - 前传之重复剔除严格劣战略的占优战略均衡

    博弈论(Game Theory) - 02 - 前传之重复剔除严格劣战略的占优战略均衡 开始 "重复剔除劣战略的严格占优战略均衡"(iterated dominance equil ...

  6. c#枚举值增加特性说明

    c#枚举值增加特性说明 通过特性给一个枚举类型每个值增加一个字符串说明,用于打印或显示. 自定义打印特性 [AttributeUsage(AttributeTargets.Field)] public ...

  7. Excel表格导入Mysql数据库,一行存入多条数据的前后台完整实现思路(使用mybatis框架)

    现在有一张Excel表格: 存入数据库时需要这样存放: 现在需要将Excel表格做处理,将每一行拆分成多条数据存入数据库. 1.首先在前台jsp页面画一个按钮:,加入点击事件: <td styl ...

  8. Scala基础 - 下划线使用指南

    下划线这个符号几乎贯穿了任何一本Scala编程书籍,并且在不同的场景下具有不同的含义,绕晕了不少初学者.正因如此,下划线这个特殊符号无形中增加Scala的入门难度.本文希望帮助初学者踏平这个小山坡. ...

  9. springMVC---简介

    SpringMVC介绍 为什么要使用springMVC? 很多应用程序的问题在于处理业务数据和显示业务数据的视图的对象之间存在紧密耦合.通常,更新业务对象的命令都是从视图本身发起的,使视图对任何业务对 ...

  10. int类型和byte类型的强制类型转换

    今天在读<Java网络编程>这本书的第二章 流 时,看到书中有一个地方关于int强制转换为byte类型时应注意的地方.这个地方有点细节,不过就应该把这种细节把握住. 情况是这样的,讲到In ...