简介

GNU Bash,又名 Bourne Again Shell。它最初发布于 1989 年,并且轻松成长为 Linux 世界中使用最广泛的 shell,甚至常见于其他一些类 Unix 系统当中。

shell解析命令行的过程以及eval命令

变量

shell中的变量都是全局变量,函数中的变量需要使用 local 将其变成局部变量,防止污染函数外的变量。

不过从严格意义上,Bash没有变量类型。Bash中的变量,在运行的时候会被展开成其对应的值(字符串)。

静态变量

在执行过程中不能改变的变量

readonly passwd_file=”/etc/passwd”
readonly group_file=”/etc/group”

变量操作

  1. 大小写切换

^大写,,小写, ~大小写切换

重复一次只匹配一个字母,重复两次则应用于所有字母。

HI=HellO
echo "$HI" # HellO
echo ${HI^} # HellO
echo ${HI^^} # HELLO
echo ${HI,} # hellO
echo ${HI,,} # hello
echo ${HI~} # hellO
echo ${HI~~} #hELLo
  1. 替换运算符
${var:-word}    # 如果var存在且非null,返回它的值;否则返回word
${var:=word} # 如果var存在且非null,返回它的值;否则将word赋值给var,并返回var的值
${var:?word} # 如果var存在且非null,返回它的值;否则显示var:word
${var:+word} # 如果var存在且非null,返回word;否则返回null

冒号(:)可省略

  1. 模式匹配运算符
${var#pattern}    匹配前缀(最小匹配),并返回余下内容
${var##pattern} 匹配前缀(最大匹配),并返回余下内容
${var%pattern} 匹配结尾(最小匹配),并返回余下内容
${var%%pattern} 匹配结尾(最大匹配),并返回余下内容

pattern为正则表达式匹配

数组

Bash 提供了一维数组变量。任何变量都可以作为一个数组;内建命令 declare 可以显式地定义数组。数组的大小没有上限,也没有限制在连续对成员引用和赋值时有什么要求。数组以整数为下标,从 0 开始。

  1. 定义和初始化数组
declare -a array            # 显示声明了数组array
array[key]=value # array[0]=one
array=(value1 value2...) # value的形式都是[subscript]=string,下标和等号可以省略,示例如下。
array=([0]=value1 [2]=value3 [3]=value[4]) # 关联数组的另一种定义方式
mydict=(["name"]=guess ["old"]=18 ["favourite"]=coconut ["my description"]="I am a student")

从上面来看数组的定义也是非常灵活多变的,能够满足我们大部分的需求,跟其其它语言最大的区别就是shell中的数组大小没有上限,也可以理解为数组是动态的。

  1. 数组的访问

    数组的任何元素都可以用${array[subscript]}来引用,花括号是必须的,以避免和路径扩展冲突。

    如果 subscript 是@或是*,它扩展为array的所有成员。

这两种下标只有在双引号中才不同。在双引号中,"${name[*]}"扩展为一个词,由所有数组成员的值组成,用特殊变量IFS的第一个字符分隔数组成员;"${array[@]}"将array的每个成员扩展为一个词。 如果数组没有成员,${name[@]} 扩展为空串。

示例--"${name[*]}""${array[@]}"的不同

#!/bin/bash

arr=("one" "two")
for i in "${arr[*]}"
do
echo ${i}
done for i in "${arr[@]}"
do
echo ${i}
done

输出如下

one two

one
two
  1. 数组的删除

    用unset来进行数组的删除
unset array[2] # 删除第三个成员
unset array # 删除整个数组
  1. 数组的长度
${#arr[@]}
${#arr[*]}
${#arr} #错误的。这个获取的是数组第一个成员的长度。
  1. 数组的”切片”操作

    获取数组的“子串“用${arr[@]:n:m}来表示,如果没有:m那么就获取从下标n开始到最后一个元素的“字串“,示例如下:
#!/bin/bash

arr=(one two three four)

echo ${arr[@]:2}
echo ${arr[@]:1:3}
echo ${arr[@]:0}

输出如下

three four
two three four
one two three four
  1. 关联数组

    shell中还可以声明一个关联数组,普通数组只能使用整数作为数组的索引,而关联数组则使用字符串作为数组的索引。这个关联数组有点像其它语言中的字典。在mac下的bash 中的declare不含这个-A这个参数。
#!/bin/bash

declare -A array

array["age"]=29
array["name"]=Yang # 输出数组的value
echo "${array[@]}" # 遍历数组的值
for a in "${array[@]}"; do
echo "${a}"
done # 通过下标获取元素值
echo "${array[age]}" # 输出数组的key
echo "${!array[@]}" # 遍历数组的key
for a in "${!array[@]}"; do
echo "${a}"
done

输出

Yang 29
Yang
29
29
name age
name

应用

  1. 判断一个指定的字符串是否在该数组中

    if echo "${ARR[@]}" | grep -w "item_1" &>/dev/null; then
    echo "Found"
    fi

四则运算

  1. bash支持的算数运算
+	 - 	* 	/

有些场景中,乘法符号需要转义

  1. 算数运算实现方式
let a=a+b			  计算结果无法直接获取,需要赋值后才能使用
var=$[算数表达式] 计算结果可以直接使用,建议使用
var=$((算数表达式)) 同上
var=$(expr arg1 arg2 arg3)
  1. 浮点数计算

使用shell内置命令bc

# 进制转换
echo "obase=2; ibase=2; 1+1" | bc # 保留精度
echo "scale=2;1/2" | bc # 多行计算
# v1=$(bc << EOF
> v2=1
> v3=2
> v2+v3
> EOF
> )
# echo $v1
3
  1. 增强型赋值
+= 	-=	 *= 	/= 	%=
let var=var1+=1
let var++ # 自增
let var-- # 自减

条件测试

分类

  • 整数测试
  • 文件测试
  • 字符测试

真返回值为true或者false

条件比较测试表达式有以下三种

[ expression ]
[[ expression ]]
test expression

整数测试

-eq:=
-ne:!=
-gt:>
-lt:<
-ge:>=
-le:<=

文件测试

  1. 存在性测试
-e file	是否存在
-f file 是否为普通文件
-d file 是否为目录
  1. 权限测试
-r file	指定文件对当前用户是否可读
-w file 指定文件对当前用户是否可写
-x file 指定文件对当前用户是否可执行
-u file 当前用户是否是文件的属主
-g file 当前用户是否是文件的属组
  1. 文件大小测试
-s file	文件存在且非空

字符测试

[[ ]]或者[ ]都可以

  1. 等值比较

=或者==注意:等号两端要有空格

  1. 不等比较

!=注意:等号两端要有空格

  1. 是否为空测试
-z string:测试字符串是否为空,空为真;
-n string:测试字符串是否不为空,不空为真;
~= 左侧的字符串能否被右侧的PATTERN所匹配

组合条件测试

主要分两类

COMMAND1 && COMMAND2
COMMAND1 || COMMAND2
! COMMAND1 [ EXPRESSION1 -a EXPRESSION2 ]
[ EXPRESSION1 -o EXPRESSION2 ]
[ ! EXPRESSION1 ]

示例,传递一个用户名参数给脚本,判断此用户的用户名跟其基本组的组名是否一致,并将结果显示出来。

#!/bin/bash
if [ $# -ne 1 ]; then
echo "Please enter a argument."
exit 1
elif ! id $1 &> /dev/null; then
echo "No such user."
exit 2
elif [ $1 == $(id $1 -g -n) ]; then
echo "Same."
else
echo "Diffrent."
fi

选择语句

case SWITCH in
value1)
statement1
...
;;
value2)
statement2
...
;;
*)
statement3
...
;;
esac

循环语句

循环需要有进入条件和退出条件

for--有限循环

# 形式1
for 变量 in 列表;do
循环体
done # 形式2
for (( expr1 ; expr2 ; expr3 )); do
循环体
done

生成整数列表

{1..100}
`seq [起始数] [步进长度] 结束数`

示例

for i in `seq 1 $a`; do echo $i; done

while--无线循环

条件满足则执行循环

while CONDITION; do
循环体
done

示例

while的特殊用法一,死循环

while :; do
循环体
done

while的特殊用法二,按行读取文件

while read LINE; do
循环体
done < /PATH/TO/SOMEFILE

until

满足条件则结束循环

until CONDITION; do
循环体
done

continue

提前结束本轮循环,进入下一轮循环

函数

  • 通过位置传递参数
  • 通过 echo 返回值
  • 通过return 返回状态码
  1. 定义

    function func_name(){
    ...函数体...
    }
  2. 直接通过函数名调用,函数名后不用加括号。

格式化输出 echo printf

echo

-n 不换行输出
-e 支持扩展

printf

使用printf可以输出更规则更格式化的结果。它引用于C语言的printf命令,但是有些许区别。

printf可以指定字符串的宽度、实现左对齐(使用减符号-)、右对齐(默认的)、格式化小数输出等。

使用printf最需要注意的两点是:

  • printf默认不在结尾加换行符,它不像echo一样,所以要手动加“\n”换号;
  • printf只是格式化输出,不会改变任何结果,所以在格式化浮点数的输出时,浮点数结果是不变的,仅仅只是改变了显示的结果。
> printf "%-5s %-10s %-4s\n" No Name Mark     # 三个%分别对应后面的三个参数
> printf "%-5s %-10s %-4.2f\n" 1 Sarath 80.34 # 减号“-”表示左对齐
> printf "%-5s %-10s %-4.2f\n" 2 James 90.998 # 5s表示第一个参数占用5个字符
> printf "%-5s %-10s %-4.2f\n" 3 Jeff 77.564

其他

位置参数 $@ $* $#

$* 表示从1开始所有位置的参数,如果扩展发生在双引号内,即"$*",则扩展包含每个参数值的单词,每个参数值用特殊表量IFS的第一个字符分割;也就是说,"$*"等价于"$1c$2c...",其中,c时特殊变量IFS的第一个字符。如果变量IFS没有定义,则参数之间默认用空格分割。

$@也扩展为从1开始的所有位置参数。但当它的扩展发生在双引号内时,每个参数都扩展为分割的单词。即:"$@"等价于"$1"、"$2" ...。参数@与*之间的区别会在for循环中体现出来。循环时用 $@

如果命令运行失败让脚本退出执行

set -o errexit
set -e

若有用未设置的变量即让脚本退出执行

set -o nounset
set -u

BASH中用 read 实现“按任意键继续”

read -s -n1 -p "按任意键继续 ... "

参数说明

-s 指输入的字符屏幕上不可件,应该说可见,但由于和终端的背景色相同,故不可见

-n 1 表示仅接收1个字符,按回车键也属于一个字符

-p 是指提示符

bash cookbook的更多相关文章

  1. Bash CookBook(一)--基础

    Bash 是brian Fox在1988年1月10号出于Richard Stallman的建议而写的.   一. 运行模板: 交互登陆的shell,登陆后bash会读取和执行/etc/profile. ...

  2. (转) [it-ebooks]电子书列表

    [it-ebooks]电子书列表   [2014]: Learning Objective-C by Developing iPhone Games || Leverage Xcode and Obj ...

  3. SHLVL 和 BASH_SUBSHELL 两个变量的区别

    SHLVL 是记录多个 Bash 进程实例嵌套深度的累加器,而 BASH_SUBSHELL 是记录一个 Bash 进程实例中多个子 Shell(subshell)嵌套深度的累加器. 看不懂上面这句话不 ...

  4. shell script 学习笔记-----shell变量

    1.在赋值语句name=value中不能存在空格,例如:name = value这样的形式会被认为是三个变量,因为本质上来说,脚本的内容就是传给shell程序的变量,而变量之间是通过空格区分的.如果想 ...

  5. shell script 学习笔记-----命令执行

    1.PATH变量:shell最主要的功能就是执行用户输入的命令,例如当用户输入一条“ls”命令之后,shell就要找到该命令对应的文件并执行.通常shell都会设置一个名叫PATH的环境变量,其中保存 ...

  6. shell script 学习笔记-----标准输出

    1.将标准输出(stdout)和标准错误输出(stderr)分别重定向到两个不同的文件 其中符号'>'默认将标准输出重定向,意思和'1>'相同,‘2>'表示重定向标准错误输出,数字1 ...

  7. 二 shell 基础

    一   文件的 权限基础 文件有三类权限   user,group,other, 权限分为 r w x  代表数字分别为 4 2 1 修改权限命令 chmod 权限还有特殊权限,在执行的时候代表某一身 ...

  8. Chef 自动化运维:初探 cookbook

    cookbook 概述 Chef 意为"厨房",我们要做"菜",自然需要有"菜谱".事实上在 Chef 中分发到各服务器节点的不是" ...

  9. Linux Shell Scripting Cookbook 读书笔记 1

    本系列文章为<Linux Shell Scripting Cookbook>的读书笔记,只记录了我觉得工作中有用,而我还不是很熟练的命令 书是很好的书,有许多命令由于我比较熟悉,可能就没有 ...

随机推荐

  1. 数据分析_numpy_基础1

    数据分析_numpy_基础1 创建数组 方法 说明 np.array( x ) 将输入数据转化为一个ndarray| np.array( x, dtype ) 将输入数据转化为一个类型为type的nd ...

  2. logstash用jdbc插件将数据库内容导入elasticsearch时间字段相差5小时

    logstash将mysql的数据导入elasticsearch之后发现时间字段的相差5个小时 解决办法: 在数据库连接配置后面加上?serverTimezone=UCT这个就OK了 logstash ...

  3. Mac word文档的消失问题以及解决方案

    最近用mac电脑上的Microsoft Word写文档时,出现一个很奇怪的现象:明明我已经保存了文档到某个目录下,但是当我退出Word后,准备去保存目录找文档时发现文档消失了,前一秒还在!!! 通过各 ...

  4. Spring中常用注解的介绍

    spring中使用注解时配置文件的写法: <?xml version="1.0" encoding="UTF-8"?> <span style ...

  5. NKOJ3772 看电影

    问题描述 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放映的是第f[i]部. 你可以选择l,r(1<=l<=r<= ...

  6. lly的数列询问(最小生成树 + 思维)

    lly的数列询问 Description 这个问题很简单,lly lly lly给你一些提示,让你试着确定长度为n n n的数列A [1] A [2] ... A [n]的值,但是他想尽一切办法为大家 ...

  7. STM32F103ZET6 PWM输出

    1.通用定时器的PWM功能 STM32F103ZET6有4个通用定时器,分别是TIM2.TIM3.TIM4.TIM5. 通用定时器由一个可编程预分频器驱动的16位自动装载计数器构成. 通用定时器的很多 ...

  8. Fiddler插件---将Mapi请求自动转为HTTPRunner测试用例(YAML格式)

    背景 继之前鼓捣出了Mapi解密插件之后,在团队内已经使用了三年之久,一跃成为团队最爱欢迎的测试工具之一(加个之一,低调谦虚一点). 随着团队推行HttpRunner搞接口自动化:编写和维护Case带 ...

  9. PTA数据结构与算法题目集(中文) 7-18

    PTA数据结构与算法题目集(中文)  7-18 7-18 银行业务队列简单模拟 (25 分)   设某银行有A.B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 —— 即当A窗 ...

  10. python 终端带颜色的打印文本

    import sys from termcolor import colored, cprint text = colored('Hello, World!', 'red', attrs=['reve ...