您的位置:首页 > 运维架构 > Shell

读《Linux Shell脚本攻略》第1章笔记

2012-11-16 17:37 239 查看
1. #!、shebang意义

Linux环境中的任何脚本语言,都是以这样一个被称为shebang的特殊行作为起始的,在这行中,字符#!被置于解释器路径之前。/bin/bash是解释器的位置http://zh.wikipedia.org/wiki/Shebang

2. echo、printf

echo 后面不用引号,用双引号,单引号区别,并总结双引号中需要转义(\)的特殊字符

printf使用引用文本或由空格分隔的参数,我们可以在printf中使用格式化字符串。我们还可以指定字符串的宽度、左右对齐方式等。在默认情况下,printf并不像echo命令一样会自动添加换行符,我们必须在需要的时候手动添加,比如在下面的脚本中:

#!/bin/bash

printf “%-5s %-10s %-4s\n” No Name Mark

printf “%-5s %-10s %-4.2f\n” 1 Sarath 80.3456

printf “%-5s %-10s %-4.2f\n” 2 James 90.9989

printf “%-5s %-10s %-4.2f\n” 3 Jeff 77.564

输出结果:

No Name Mark

1 Sarath 80.35

2 James 91.00

3 Jeff 77.56

%s、%c、%d、%f都是格式化字符,其所对应的参数可以置于带引号的格式化字符串之后。

%-5s格式化为左对齐宽度为5的字符串替代(-表示左对齐),如果不用-指定对齐方式,字符串则采用右对齐形式。宽度指定了保留给某个变量的字符数,列 和列本身有一个空字符串。对Name而言,保留宽度为10,所以看起来列和列之间有11个字符串。因此,任何Name字段的内容都会被显示在10字符宽的 保留区域内,如果内容不足10字符,余下的则会以空格符填充。如果超过10个字符,列对齐效果将被打乱。

%-4.2,其中.2指定保留2个小数位,对小数部分四舍五入。注意,在每行格式字符串后都有一个换行符\n。

3. 颜色输出

打印彩色文本对应颜色码:重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37

打印彩色背景对应颜色码:重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47

echo -e “\e[1;31mThis is red text\e[0m"

echo -e "\e[1;42mGreen background\e[0m"

4. cat /proc/`pgrep java`/environ | tr '\0' '\n'

tr '\0' '\n' 重新格式化输出,将\0(null字符)替换成\n(换行)

5. bc

设定小数精度:scale=2 将小数位个数设置为2.

echo "scale=2;3/8" | bc

.37

进制转换:

echo "obase=2;100" | bc

1100100 #十进制转换成二进制

echo "obase=10;ibase=2;1100100" | bc

100 #二进制转换成十进制

计算平方以及平方根:

echo "sqrt(100)" | bc

10

echo "10^10" | bc

10000000000

6. stdin、stdout、stder、tee

0 - stdin(标准输入)

1 - stdout (标准输出)

2 - stderr (标准错误)

$echo a1 > a1;cp a1 a2;cp a2 a3 ;chmod 000 a1

$ cat * | tee -a out.txt | cat -n

cat: a1: Permission denied

1 a1

2 a1

$ cat out.txt

a1

a1

tee命令接收到来自stdin的数据。它将stdout的一份副本写入文件out.txt。同时将另一份副本作为后续命令的stdin。命令cat -n将从stdin中接收到的每一行数据前加上行号并写入stdout。-a参数可以用于追加内容

可以使用stdin作为命令参数,只需要将-作为命令的文件名参数即可:

$ echo who is this | tee -

who is this

who is this

7. 自定义文件描述符

文件描述符是用于访问文件的一个抽象指针。存取文件离不开被称为“文件描述符”的特殊数字。0、1和2分别是stdin、stdout和stderr的预留描述符。

我们可以使用exec命令创建自定义的文件描述符。3中模式:只读模式;截断模式;追加模式

为读取文件创建一个文件描述符:

# touch input.txt

# exec 3<input.txt #使用文件描述符3打开并读取文件

# echo This is a test line > input.txt

# exec 3<input.txt

# cat <&3

This is a test line

如果要再次读取,我们就不能再继续使用文件描述符3了,而是需要用exec重新分配文件描述符3以便用于读取。

创建一个文件描述符用户写入(截断模式):

# exec 4>output.txt #打开文件用于写入

# echo newline >&4

# cat output.txt

newline

创建一个文件描述符用于写入(追加模式):

# exec 5>>input.txt

# echo appended line >&5

# cat input.txt

This is a test line

appended line

8. 数组和关联数组

bash同时支持普通数组和关联数组。普通数组只能使用整数作为数组索引,而关联数组可以使用字符串作为数组索引。关联数组是从bash4.0开始被引入。

定义关联数组

首先需要使用单独的声明语句将一个变量名声明为关联数组。声明语句如下:

# declare -A ass_array

声明之后,可以用两种方法将元素添加到关联数组中。

1). 利用内嵌索引值列表法,提供一个索引值列表:

# ass_array=([index1]=val1 [index2]=val2)

2). 使用独立的索引值进行赋值:

# ass_array[index1]=val1

# ass_array[index2]=val2

列出数组索引

每一个数组元素都有一个索引用于查找。普通数组和关联数组具有不同的索引类型

9. 获取终端信息

获取终端的行数和列数:

tput cols

tput lines

打印出当前终端名:

tput longname

将光标移动到方位(100,100)处:

tput cup 100 100

设置终端背景色:

tput setb no #no取值在0~7之间

将文本前景色设置为白色:

tput serf no #no取值在0~7之间

设置文本样式为粗体:

tput bold

删除当前光标位置到行尾的所有内容:

tput ed

在输入密码的时候,不能让输入的内容显示出来,在下面的例子中,我们将看到如何使用stty来实现这个要求:

#!/bin/bash

#Filename:password.sh

echo -e “Enter password: ”

stty -echo

read password

stty echo

echo

echo $password

echo Password read.

其中,选项-echo禁止将输出发送到终端,而选项echo则允许发送输出。

用tput和sleep从0开始计数到40:

#!/bin/bash

#Filename sleep.sh

echo -n Count:

tput sc

count=0;

while true;

do

if [ $count -lt 40 ];

then let count++;

sleep 1;

tput rc

tput ed

echo -n $count;

else exit 0;

fi

done

在上面的例子中,变量count初始化为0,随后每循环一次便增加1。echo语句打印出count的值。我们用tput sc储存光标位置。在每次循环中,我们通过恢复之前储存的光标位置,在终端中打印出新的count值。恢复光标位置的命令是tput rc。tput ed清除从当前光标位置到行尾之间的所有内容,使得旧的count值可以被清除并写入新值。循环内的1s延时是通过sleep命令来实现的。

10. 调试shell脚本

set -x:在执行时显示参数和命令。

set +x:禁止调试。

set -v:当命令进行读取时显示输入。

set +v:禁止打印输入。

11. Fork炸弹

: () {

: | : &

}; :

: 是函数名,执行一个调用自己的递归并且 pipe 到自己,& 表示后台执行程序,最后的一个 : 是在函数外调用和执行 : () 这个函数的意思

12. read

参数可以组合使用

# read -n 2 var 读取2个字符并存入变量var

# echo $var

# read -s var #用不回显的方式读取密码

# echo $var

# read -p “Enter input:” var #显示提示信息

# read -t 2 var #在2s内将输入的字符串存入到变量var

# read -d “:” var #使用:作为定界符结束输入行

13. 字段分隔符和迭代器

内部字段分隔符(Internal Field Separator, IFS)

# cat ifs.sh

#!/bin/bash

data=”name,sex,rollno,location”

oldIFS=$IFS

IFS=”,”

for item in $data;

do

echo Item:$item

done

IFS=$oldIFS

结果如下:

Item:name

Item:sex

Item:rollno

Item:location

IFS的默认值为空白符(换行符、制表符或者空格)。

当IFS被设置为逗号时,shell将逗号解释成一个定界符,因此变量$item在每次迭代中读取由逗号分隔的字串作为变量值。

如果没有把IFS设置成”,”,那么上面的脚本将会全部数据作为单个字符串打印出来。

14. Bash多种类型的循环

for 循环

while 循环

until 循环

&&逻辑与运算符 ||逻辑或运算符

15. 算术比较

条件通常被放置在封闭的中括号内。一定要注意在[]与操作数之间有一个空格。

-gt:大于

-lt:小于

-ge:大于或等于

-le:小于或等于

-eq:等于

-ne:不等于

可以结合 -a 逻辑与 -o 逻辑或条件进行测试

文件系统相关属性测试:

[ -f $file_var ] 如果给定的变量包含正常的文件路径或文件名,则返回真

[ -x $var ] 如果给定的变量包含的文件可执行,则返回真

[ -d $var ] 如果给定的变量包含的是目录,则返回真

[ -e $var ] 如果给定的变量包含的文件存在,则返回真

[ -c $var ] 如果给定的变量包含的是一个字符设备文件的路径,则返回真

[ -b $var ] 如果给定的变量包含的是一个块设备文件的路径,则返回真

[ -w $var ] 如果给定的变量包含的文件可写,则返回真

[ -r $var ] 如果给定的变量包含的文件可读,则返回真

[ -L $var ] 如果给定的变量包含的是一个符号链接,则返回真

字符串比较:

使用字符串比较是,最好用双中括号,因为有时候采用单个中括号会产生错误,所以最好避开他们。

[[ $str1 = $str2 ]] 当str1等于str2时,返回真。str1和str2包含的文本是一模一样

[[ $str1 == $str2 ]] 这是检查字符串是否相等的另一种写法。也可以检查两个字符串是否不同

[[ $str1 != $str2 ]] 如果str1和str2不相同,则返回真

[[ $str1 > $str2 ]] 如果str1的字母序比str2大,则返回真

[[ $str1 < $str2 ]] 如果str1的字母序比str2小,则返回真

[[ -z $str1 ]] 如果str1包含的是空字符串,则返回真

[[ -n $str1 ]] 如果str1包含的是非空字符串,则返回真

注意:在=前后各有一个空格,如果忘记加空格,那就不是比较关系了,而变成了赋值语句

转载请注明:http://blog.linuxeye.com/shell/225.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: