Bash 脚本笔记

bash 特殊字符(上)

1.将文件中内容清空而保留文件

cat /dev/null > example.file

因为 /dev/null 是空的,重定向到 example.file后,就清空了example.file里的内容。

2. 单分号(;)与双分号(;;)

  • 使用单分号(;)可以在一行中写入多条语句
 echo hello; echo there
  • 使用双分号(;;)可以终止case 选项
varname=b

case "$varname" in
    [a-z]) echo "abc";;
    [0-9]) echo "123";;
esac

3.点号(.)

bash中的source命令用于在当前bash环境下读取并执行 FileName.sh中的命令。

$ source test.sh
Hello World
$ . test.sh
Hello World

4.双引号与单引号

  • 双引号(")
    “String” 将会阻止(解释)String中大部分特殊的字符。
  • 单引号(’)
    ‘Sting’ 将会阻止String中所有特殊字符的解释,这是一种比使用双引号更强烈的形式。

5.斜杠与反斜杠

  • 斜杠(/)
    文件名路径分隔符。分隔文件名不同的部分(如 /home/bozo/projects/Makefile)。也可以用来作为除法算术操作符。注意在linux中表示路径的时候,许多个 / 跟一个 / 是一样的。/home/shiyanlou等同于 ///home//shiyanlou

  • 反斜杠()
    一种对单字符的引用机制。\X 将会“转义”字符X。这等价于“X”,也等价于’X’。\通常用来转义双引号(“)和单引号(’),这样双引号就不会被解释成特殊含义了。

    符号 说明
    \n 表示新的一行**(newline)**
    \r 表示回车**(return)**
    \t 表示水平制表符**(tab)**
    \v 表示垂直制表符**(vertical)**
    \b 表示后退符**(back)**
    \a 表示"alert"(蜂鸣或者闪烁)(alert)
    \0xx 转换为八进制的ASCII码, 等价于0xx
    " 表示引号字面的意思

转义符也提供续行功能,也就是编写多行命令的功能。

每一个单独行都包含一个不同的命令,但是每行结尾的转义符都会转义换行符,这样下一行会与上一行一起形成一个命令序列。

6.反引号(`)

命令替换
反引号中的命令会优先执行,如:

cp `mkdir back` test.sh back

先创建了back 目录,然后复制 test.sh到 back 目录

7.冒号(?

  1. 空命令
    等价于“NOP”(no op,一个什么也不干的命令)。也可以被认为与shell的内建命令 true 作用相同。":" 命令是一个bash 的内建命令,它的退出码(exit status )是(0)。
    如:
#! /bin/bash

while :
do
	echo "endless loop"
done

等价于

#! /bin/bash

while true
do
	echo "endless loop"
done

可以在if/then中作占位符:

#! /bin/bash

condition=5

if [ $condition -gt 0] # -gt (greater than),-lt (less then), -eq (equals)
then : # 什么也不做,退出分支
else
	echo "$condition"
fi
  1. 变量扩展/子串替换
    在与 > 重定向操作符结合使用时,会把一个文件清空,但是并不会修改这个文件的权限。如果之前这个文件并不存在,那么就创建这个文件。
: > test.sh # 文件“test.sh”现在被清空了
# 与 cat /dev/null > test.sh 的作用相同
# 然而, 这并不会产生一个新的里程,因为“:”是一个内建命令。

在与 >> 重定向操作符结合使用时,将不会对预先存在的目标文件 (: >> target_file)产生任何影响。如果这个文件之前不存在,那么就创建它。(仅使用 >> 和 使用 : >> 效果相同)

“:”还用来在 /etc/passwd 和 $PATH变量中做分隔符,如:

$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games

8.问号

测试操作符
在一个双括号结构中(在双括号结构中可以进行数学运算),?就是C语言中的三元操作符,如:

#! /bin/bash

a=10
(( t=a<50 ? 8 : 9 ))
echo $t

9.美元符号($)

进行变量引用。

bash 特殊字符(下)

1.小括号()

  1. 命令组
    在括号中的命令列表,将会作为一个子shell来运行。
    在括号中的变量,由于是在子shell中,所以对于脚本剩下的部分是不可用的。父进程,也就是脚本本身,将不能读取在子进程中创建的变量,也就是在子shell中创建的变量。
#! /bin/bash

a=123
( a=321; )
echo "$a" # a 的值为123而不是321,因为括号将判断为局部变量
  1. 初始化数组
    创建数组
#! /bin/bash

arr=(1 4 5 7 9 21)
echo ${arr[3]} # get a value of arr

运行结果为7。

大括号(花括号{})

  1. 文件名扩展
    复制 t.txt 的内容到 t.back 中
#! /bin/bash

if [ ! -w 't.txt' ]
then
	touch t.txt
fi
echo 'test text' >> t.txt
cp t.{txt,back}

可以实现复制一个文件并进行重命名操作

cp t.{txt,back} 命令与 cp t.txt t.back 命令功能一样

注意: 在大括号中,不允许有空白,除非这个空白被引用或转义。

  1. 代码块
    代码块,又被称为内部组,这个结构事实上创建了一个匿名函数(一个没有名字的函数)。然而,与“标准”函数不同的是,在其中声明的变量,对于脚本其他部分的代码来说还是可见的。
#! /bin/bash

a=123
{ a=321; }
echo "a= $a"

结果输出为 a=321

中括号([ ])

  1. 条件测试
    条件测试表达式放在 [ ]中。
#! /bin/bash
a=5
if [ $a -lt 10]
then
	echo "a: $a"
else
	echo 'a>10'
fi

双中括号 [[ ]] 也用作条件测试(判断)。
2. 引用数组元素
在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号。

#! /bin/bash

arr(12 22 32)
arr[0]=10
echo ${arr[0]}

4. 尖括号(< 和 >)

重定向
test.sh > filename : 重定向test.sh 的输出到文件 filename 中。如果filename 存在的话,那么文件中的内容将会被覆盖。

test.sh &> filename: 重定向 test.sh 的 stdout (标准输出)和stderr(标准错误) 到 filename中。

test.sh >&2 : 重定向 test.sh 的 stdout 到 stderr中。

test.sh >> filename: 把test.sh 的输出追加到文件filename中。如果filename不存在的话,将会被创建。

5. 竖线 (|)

管道
分析前面命令的输出,并将输出作为后面命令的输入。这是一种产生命令链的好方法。
test.sh

#! /bin/bash

tr 'a-z' 'A-Z'
exit0
chmod u+x test.sh
ls -l | ./test.sh

输出的内容均变为了大写字母。

6.破折号(-)

  1. 选项,前缀
    在所有的命令内如果想使用选项参数的话,前面都要加上"-"。
  2. 用于重定向stdin或stdout
    下面脚本用于备份最后24小时当前目录下所有修改的文件。
#! /bin/bash

BACKUPFILE=backup-$(date +%m-%d-%Y)# $( command ),可以在$()中执行命令
# 在备份文件中嵌入时间
archive=${1:-$BACKUPFILE}
# 如果在命令行中没有指定备份文件的文件名
# 那么将默认使用"backup-MM-DD-YYYY.tar.gz"

tar cvf - `find . -mtime -1 -type f -print` > $archive.tar
gzip $archive.tar
echo "Directory $PWD backed up in archive file \"$archive.tar.gz\"."
exit 0

7.波浪号(~)

~ 表示home目录

变量和参数

1.变量定义

  1. 概念
    变量的名字就是变量保存值的地方,引用变量的值就叫做变量替换。
    如果variable是一个变量的名字,那么$variable就是引用这个变量的值,即这变量所包含的数据。
    variable事实上只是{variable}的简写形式。在某些上下文中,variable可能会引起错误,这时候就需要用{variable}了
  2. 定义变量
    定义变量时,变量名不加美元符号($, PHP语言中变量需要),如:myname=“shiyanlou”
    注意:变量名和等号之间不能有空格。

2.使用变量

变量名前加美元符号($)
加花括号帮助解释器识别变量的边界。推荐给所有变量加花括号。
已定义的变量可以重新被定义。

3.只读变量

使用readonly命令可以将变量定义为只读变量,只读变量的值不能被改变。

#! /bin/bash
myUrl="http://www.shiyanlou.com"
readonly myUrl
myUrl="http://www.shiyanlou.com"

运行脚本,结果如下:

/bin/sh: NAME: This variable is read only.

4. 特殊变量

  1. 局部变量
    这种变量只有在代码块或者函数中才可见。
  2. 环境变量
    这种变量将影响用户接口和shell的行为。
    在通常情况下,每个进程都有自己的“环境”,这个环境是由一组变量组成的,这些变量中存有进程可能需要引用的信息。在这种情况下,shell与一个一般进程没什么区别。
  3. 位置参数
    从命令行传递到脚本的参数:0,1,2,3…
    0就是脚本文件自身的名字,1就是第一个参数,2就是第二个参数,3就是第三个参数,然后是第四个… 9之后的位置参数就必须厄特大括号括起来了,比如,{10},{11},{12}
  • $# : 传递到脚本的参数个数
  • $* : 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过9个
  • : 脚本运行的当前进程ID号
  • $! : 后台运行的最后一个进程的进程ID号
  • @ : 与 * 相同,但是使用时加引号,并在引号中返回每个参数
  • $ : 显示shell 使用的当前选项,与set命令功能相同
  • $? : 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

基本运算符

算数运算符

#! /bin/bash

a=10
b=20

val=`expr $a + $b`
val=`expr $a \* $b`
if [ $a == $b ]
then 
	echo "a == b"
fi
  • 原生bash 不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr , expr 最常用
  • expr 是一款表达式计算工具,使用它能完成表达式的求值操作。(expression 表达式)
  • 注意使用反引号
  • 表达式和运算符之间要有空格 $a + $b写成 a + a+ a+b不行
  • 条件表达式要放在方括号之间,并且要有空格[ $a == b ] 写 成 [ b ] 写成 [ b][a==$b]不行
  • 乘号(*) 前面必须加反斜杠()才能实现乘法运算

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字

运算符说明
-eq检测两个数是否相等,相等返回 true。
-ne检测两个数是否相等,不相等返回true。
-gt检测左边的数是否大于右边的,如果是返回true。
-lt检测左边的数是否小于右边的,如果是返回true。
-ge检测左边的数是否大于等于右边的,如果是返回true。
-lt检测左边的数是否小于等于右边的,如果是返回true。

3.逻辑运算符

运算符说明
&&逻辑的 AND
||逻辑的 OR

4. 字符串运算符

运算符说明
=检测两个字符串是否相等,相等返回true。
!=检测两个字符串是否相等,不相等返回true。
-z检测字符串长度是否为0,为0返回true。
-N检测字符串长度是否为0,不为0返回true。
str检测字符串是否为空,不为空返回true。

5.文件测试运算符

操作符说明
-e文件存在
-a文件存在,这个选项的效果与-e相同。但已被弃用,不鼓励使用。
-f表示这个文件是一个一般文件(不是目录或者设备文件)
-s文件大小不为才零
-d表示这是一个目录
-b表示这是一个块设备(软盘,光驱等)
-c表示这是一个字符设备(键盘,modem,声卡等)
-p这个文件是一个管道
-h这是一个符号链接
-L这是一个符号链接
-S表示这是一个socket
-t文件(描述符)被关联到一个终端设备上,这个测试选项一般被用来检测脚本中的stdin([ -t 0 ]) 或者 stdout([ -t 1 ]) 是否来自于一个终端。
-r文件是否具有可写权限(指的是正在运行这个测试命令的用户是否具有读权限)
-w文件是否具有可写权限(指的是正在运行这个测试命令的用户是否具有写权限)
-x文件是否具有可执行权限(指的是正在运行这个测试命令的用户是否具有可执行权限)
-gset-group-id(sgid)标记被设置到文件或目录上
-k设置粘贴位
-O判断你是否是文件的拥有者
-G文件的group-id 是否与你的相同
-N从文件上一次被读取到现在为止,文件是否被修改过
f1 -nt f2文件f1 比文件f2 新
f2 -ot f2文件f1比文件f2旧
f1 -ef f2文件f1和文件f2是相同文件的硬链接
!“非”,反转上边所有测试的结果(如果没给出条件,那么返回真)

expr 只能用于整数计算,可以使用 bc 或者 awk 进行浮点数运算。

流程控制

1. if else

和 Java 、PHP等语言不一样,shell的流程控制不可为空。
在sh/bash里可不能这么写,如果else 分支没有语句执行,就不要写这个else。

  1. if
    if 语句语法格式:
if condition
then 
	command1
	command2
	...
	commandN
fi
  1. if else
    if else 语法格式:
if condition
then
	command1
	command2
	...
	commandN
else
	command
fi

if-elif-else 语法格式:

if condition1
then
	command1
elif condition2
then
	command2
else
	commandN
fi

2. for循环

for 循环的一般格式为:

for var in item1 item2 ... itemN
do
	command1
	command2
	...
	commandN
done

3.while 语句

while 循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:

while condition
do
	command
done
#! /bin/bash
int=1
while(( $int<=5 ))
do
	echo $int
	let "int++"
done

let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。

4.无限循环

无限循环语法格式:

while :
do
	command
done

或者

while true
do
	command
done

或者

for (( ; ; ))

5. until循环

until循环执行 一系列命令直至条件为真时停止。until循环与while循环处理方式上刚好相反。一般while循环优于until循环,但某些极少数情况下,until循环更加有用。until语法格式:

until condition
do
	command
done

条件可为任意测试条件,测试发生在循环末尾,因此循环至少执行一次,请注意这一点。

6.case

Shell case 语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。case 语句格式如下:

casein
模式1)
	command1
	command2
	...
	commandN
	;;
模式2)
	comamnd1
	command2
	...
	commandN
	;;
esac
  • 取值后面必须为单词 in, 每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至;;。
  • 取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

7.跳出循环(break)

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break 和 continue。
break 命令
break 命令允许跳出所有循环(终止执行后面的所有循环)。

8. continue

跳出当次循环,直接进行下一次循环。

9. esac

case 的语法和 C family 语言差别很大,它需要一个esac (就是case反过来)作为结束标记,每个case 分支用右圆括号开始,用两个分号表示 break.

函数

1.函数定义

shell中函数的定义格式如下:

[ function ] funname [()]
{
	action;
	...
	[return int;]
}

说明:

  • 可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
  • 参数返回,可以显示加return返回,如果不加,则以最后一条命令运行结果,作为返回值。return 后跟数据 n(0-255)
  • 函数返回值在调用该函数后通过 $? 来获得
  • 所有函数在使用前必须先定义。

2.函数参数

在shell中,调用函数时可以向其传递参数。在函数体内部,通过n的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…带参数的函数示例:

#!/bin/bash
funWithParam(){
    echo "The first parameter is $1 !"
    echo "The second parameter is $2 !"
    echo "The tenth parameter is $10 !"
    echo "The tenth parameter is ${10} !"
    echo "The eleventh parameter is ${11} !"
    echo "The total number of parameters is $# !"
    echo "Outputs all parameters as a string $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

注意:
10 无 法 获 取 到 第 十 个 参 数 , 获 取 第 十 个 参 数 需 要 10无法获取到第十个参数,获取第十个参数需要 10{10}。当n>=10时,需要使用${n}来获取参数。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值