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

循环:

正常的for循环:

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

数字序列循环:

for i in `seq `; do
echo "$i"
done

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

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

C语言风格的for循环:

for (( i=; i<; i++ )); do
echo "$i"
done

for循环迭代文本

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

a="ab cd
ef" for i in $a; do
echo "$i"
done

输出结果:

ab
cd
ef

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

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

数学计算

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

(( a=+ ))
echo $a
#

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

变量:

间接引用:

a=b
b=
echo ${!a}
#

效果等同于 eval echo \$$a

特殊字符转义

包含特殊字符的字符串:

echo "ab\ncd"

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

# a="ab\ncd"
# echo "length of var a is ${#a}" length of var a is

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

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

# a=$'\x61\n\x62'
# echo "$a"
a
b

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

字符串操作

变量值字符截取:

a="abcdefg"
echo ${a:}
# cdefg
echo ${a::}
# cde

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

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

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

变量赋值安全

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

unset a
unset b
b="" # a没有定义,b定义了但是空值
echo ${a-}  # 如果没定义,则表达式采用默认值789
#
echo ${a:-} # 如果没定义或是空值,则表达式采用默认值789
#
echo ${b-} # 如果没定义,则表达式采用默认值789,b定义了
#
echo ${b:-} # 如果没定义或是空值,则表达式采用默认值789
#
echo $a # 原变量并没有被赋值
#
echo $b # 原变量并没有被赋值
#
b=
echo ${b-} # 如果变量已经被赋值,则不改变原有值
#
unset a
echo ${a=} # 如果a没定义,则表达式采用默认值,并给a赋值
#
echo $a
# # a已经被赋值了
a=""
echo ${a=}
#
echo ${a:=} # 加冒号:的作用和之前一样
#
echo $a
#

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

位置变量

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

${}

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

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

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

echo '
for i in "$@"; do
echo "$i"
done
for i in "$*"; do
echo "$i"
done
' > myscript.sh
chmod myscript.sh
./myscript.sh abc def

结果是:

abc

def
abc def

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

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

echo '
for i in "$@"; do
echo "$i"
done
for i in $@ ; do
echo "$i"
done
' > myscript.sh
chmod myscript.sh
./myscript.sh abc "123 def"

结果是:

abc
def
abc def

for循环使用数组

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

字符串比较

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

[ "abc" = "abc" ]
echo $?
#

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

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

注意这里正则表达式不能用引号括起来,而且只支持基本的正则,不支持如“\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. SQL Server 中统计信息直方图中对于没有覆盖到谓词预估以及预估策略的变化(SQL2012-->SQL2014-->SQL2016)

    本位出处:http://www.cnblogs.com/wy123/p/6770258.html 统计信息写过几篇了相关的文章了,感觉还是不过瘾,关于统计信息的问题,最近又踩坑了,该问题虽然不算很常见 ...

  2. bootstrap快速入门笔记(五)-文本元素类,各种标签,排版

    1,h1到h6这里也有定义了 2,全局元素被直接赋予font-size 设置为 14px,line-height 设置为 1.428,<p> (段落)元素还被设置了等于 1/2 行高(即 ...

  3. (函数封装)获取class名称

    使用原生JavaScript,获取类操作符时:即使使用getElementByClassName,在Firefox和IE9以下是不兼容的.Firefox下是可以用它获取的到元素而IE不行,一般框架都会 ...

  4. linux 下创建管理员权限账户

    1.添加用户,首先用adduser命令添加一个普通用户,命令如下: #adduser tommy //添加一个名为tommy的用户 #passwd tommy //修改密码 Changing pass ...

  5. ubuntu下搭建nginx+mysql+php-fpm站点

    概述 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器.  nginx的优势在于能以低内存高 ...

  6. C#控制台程序使用Log4net日志组件

    1.Log4net一般都不陌生,但是在配置上不同类型的项目又不相同的地方比如C#控制台程序和C# MVCWeb项目,拿控制台项目为例   项目源码在文章底部 2.首先创建一个控制台程序,引入Log4n ...

  7. C#基础知识-数据类型(一)

    俗话说温故而知新,学习一门知识最好的方法就是不断的去咀嚼回味,学习编程更是如此.对于.NET平台中的C#语言而言,有着强大的类库.不断的在更新迭代几乎每隔一年都会更新一个新的模块,.NET Framw ...

  8. Python冒泡算法和修改配置文件

    先学习之前未完成的冒泡算法 li = [13,22,6,99,11] 从小到大 从第一个数字比较把大的往后移位 for m in range(4): num1 = li[m] num2 = li[m+ ...

  9. Android Studio 首坑 Gradle sync failed: Cause: error in opening zip file 的错误

    前言 今天安装Android studio 2.3.1时发生了一个错误,安装完成后创建第一个Hello World项目是报错.经过这个百度后,结果没有一个靠谱的.将拆解经过记录一下. 环境: 操作系统 ...

  10. Mongodb安装启动详解

    最近在倒腾node+mongodb,安装mongodb的时候开始遇到很多问题,然后折腾了好几次,直到可以很顺利完成安装 ,所以把安装的过程记录下来. 线上系统基本上都是linux的,所以只安装了lin ...