第1章 小试牛刀

第1章
1.1 简介
#!/bin/bash

给脚本赋予执行权限
chmod a+x script.sh
1.2 终端打印
echo 用于终端打印的基本命令
★ 使用不带引号的echo时,以为在bash shell中被用作命令定界符
★ 以echo hello ; hello 为例,echo hello被视为一个命令,第二个hello则被视为另一个命令
★ 使用带单引号的echo时,Bash不会对引号中的变量(如$var)求值,而只是照原样显示

注意:当在echo中使用带双引号的文本时,你应该在echo之前使用 set +H,以便能正确的显示!。 或者加转义符(\)将!转义。

set命令说明:
功能说明:设置shell。
语  法:set [+-abCdefhHklmnpPtuvx]

补充说明:用set 命令可以设置各种shell选项或者列 出shell变量.单个选项设置常用的特性.在某些选项之后-o参数将特殊特性打开.在某些选项之后使用+o参数将关闭某些特性,不带任何参数的set命 令将显示shell的全部变量.除非遇到非法的选项,否则set总是返回ture.

参  数:

allexport -a 从设置开始标记所有新的和修改过的用于输出的变量
braceexpand -B 允许符号扩展,默认选项
emacs 在进行命令编辑的时候,使用内建的emacs编辑器, 默认选项
errexit -e 如果一个命令返回一个非0退出状态值(失败),就退出.
histexpand -H 在做临时替换的时候允许使用!和!! 默认选项
history 允许命令行历史,默认选项
ignoreeof 禁止coontrol-D的方式退出shell,必须输入exit。
interactive-comments 在交互式模式下, #用来表示注解
keyword -k 为命令把关键字参数放在环境中
monitor -m 允许作业控制
noclobber -C 保护文件在使用重新动向的时候不被覆盖
noexec -n 在脚本状态下读取命令但是不执行,主要为了检查语法结构。
noglob -d 禁止路径名扩展,即关闭通配符
notify -b 在后台作业以后通知客户
nounset -u 在扩展一个没有的设置的变量的时候, 显示错误的信息
onecmd -t 在读取并执行一个新的命令后退出
physical -P 如果被设置,则在使用pwd和cd命令时不使用符号连接的路径 而是物理路径
posix 改变shell行为以便符合POSIX要求
privileged 一旦被设置,shell不再读取.profile文件和env文件 shell函数也不继承任何环境
verbose -v 为调试打开verbose模式
vi 在命令行编辑的时候使用内置的vi编辑器
xtrace -x 打开调试回响模式


printf命令,用于终端打印,其使用参数和C语言中一致

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

需要注意的是:printf需要手工换行(\n)。


1.2.2 补充内容
1.0 在echo中转义换行符
在echo中,如果要使用转义序列,可以使用 echo –e “包含转义序列的字符串”。例如:
echo –e “1\t2\t3”
1 2 3
将\t转换为Tab键

2.0 打印彩色输出
echo -e "\e[1;31m This is red text \e[0m"
说明: \e[1;31m 将颜色设置为红色; \e[0m将颜色重新置回
经常使用的颜色有:重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47


echo命令:
功能说明:显示文字。
语   法:echo [-ne][字符串]或 echo [--help][--version]
补充说明:echo会将输入的字符串送往标准输出。输出的字符串间以空白字符隔开, 并在最后加上换行号。
参   数:-n 不要在最后自动换行
-e 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般
文字输出:
\a 发出警告声;
\b 删除前一个字符;
\c 最后不加上换行符号;
\f 换行但光标仍旧停留在原来的位置;
\n 换行且光标移至行首;
\r 光标移至行首,但不换行;
\t 插入tab;
\v 与\f相同;
\\ 插入\字符;
\nnn 插入nnn(八进制)所代表的ASCII字符;
–help 显示帮助
–version 显示版本信息

1.3 玩转变量和环境变量
环境变量: evn 命令
对于每个进程,在其运行时的环境变量可以使用如下命令进程查看:
cat /proc/$PID/environ
注:$PID 为具体的进程号

命令:pgrep 显示进程对应的进程ID信息。
经常要查看进程的信息,包括进程的是否已经消亡,通过pgrep来获得正在被调度的进程的相关信息。pgrep通过匹配其程序名,找到匹配的进程
重要选项
-l 同时显示进程名和PID
-o 当匹配多个进程时,显示进程号最小的那个
-n 当匹配多个进程时,显示进程号最大的那个
注:进程号越大,并不一定意味着进程的启动时间越晚


pgrep命令相当于:
ps –eo pid,cmd | awk ‘{print $1,$2}’ | grep KeyWord


1.3.2 实战演练
定义变量:
var=value 或 var=”xxxx” 这是赋值操作

var = value 这个是相等操作

打印变量:
echo $var

echo ${var}

其他常用环境变量: HOME,PWD,USER,UID,SHEEL等。

export命令用来设置环境变量
例如: export PATH=”$PATH:/home/user/bin”

1.3.3补充内容
1.0 获取字符串的长度
var=1234567
length=${#var}
echo length

2.0 识别当前shell版本
echo $SHELL

echo $0

3.0 切换用户
su root
su tingyu

4.0 检查是否为超级用户
#检查是否是超级用户
echo "******检查是否是超级用户***********"
if [ $UID -ne 0 ]; then
echo Nor root user. Please run as root
else
echo "Root user"
fi

root用户的UID为0


5.0 习惯Bash提示字符串


1.4 通过shell进行数学运算
在Bash shell 环境中,可以利用let, (()) 和[] 执行基本的算术运算,而在进行高级操作时,expr和bc 这两个工具也会非常有用。

1.4.2 实战演练

no1=4;
no2=5;

let result=no1+no2;
echo "执行的结果为: ${result}"

let result--
let result--

echo "resule--的结果为: ${result}"

let result++

echo "resule++的结果为: ${result} "

echo "******操作符[]的使用方法******"

result1=$[no1+no2]

result2=$[ $no1 + 5 ]

result3=$((no1 + 50 ))

result4=expr 3 + 4

result5=$(expr $no1 + 5)

echo "result1的值为: ${result1}"

echo "result2的值为: ${result2}"

echo "result3的值为: ${result3}"

echo "result4的值为: ${result4}"

echo "result5的值为: ${result15}"


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

let 和 expr只支持整数运算,而不支持浮点数运算

bc可以执行浮点数运算并应用一些高级函数

#bc运算
echo "bc运算"
echo "4 * 0.56" | bc

no=54;
result6=`echo "$no * 1.5" | bc`
echo $result6


#设定小数精度
echo "设定小数精度"
echo "scale=2;3/8" | bc

#进制转换
echo "进制转换"
no=100;
echo "obase=2;$no" | bc

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


#计算平方以及平方根
echo "计算平方以及平方根"
echo "sqrt(100)" | bc #计算平方根
echo "10^10" | bc #计算10的10次方


1.5 玩转文件描述符和重定向
0----stdin 标准输入
1--- stdout 标准输出
2--- stderr 标准错误

可以将某个文件描述符的内容重定向到另一个文件描述符中。

1.5.2 实战演练
echo “This is siamle text1” > temp.txt
echo “This is siamle text 2” >> temp.txt

成功和不成功的命令:
当一个命令发送错误并退回时,它会返回一个非0的退出状态,而当命令成功完成时,它会返回数字0,退出状态可以从变量 $? 中获得。

◆将stderr 文本打印到屏幕
ls + > out.txt
◆将stderr 重定向到out.txt
ls + 2> out.txt
◆将stderr单独重定向到一个文件,将stdout重定向到另一个文件
ls + 2>stderr.txt 1>stdout.txt
◆将stdout和stderr重定向到同一个文件
ls + 2>&1 output.txt
或者
ls &> out.txt
◆将文件重定向位桶(bit bucket)或黑洞
some_command 2> /dev/null
这个命令会将stderr的输出丢到文件 /dev/null 中。 /dev/null 是一个特殊的设备文件,这个文件接收到的任何数据都会被丢弃。因此null设备也被称为位桶或黑洞

tee命令:
作用:可以一方面将数据重定向到文件,另一方面还可以提供一份重定向数据的副本作为后续命令的stdin。
command | tee FILE1 FILE2


例如:cat a* |tee out.txt | cat -n


tee命令接收来自stdin的数据,它将stdout的一份副本写入文件out.txt,同时将另一份副本作为后续命令的stdin。
cat –n 将从stdin中接收到的每一行数据前加上行号并写入stdout;


1.5.3 补充内容
1. 将文件重定向到命令
cmd < file
2. 重定向脚本内部的文本块
#! /bin/bash
cat <> out1.txt
LOG FILE HEADER
THIS IS A TEXT LOG FILE
FUNCTION:SYSYTEM STATISTICS
EOF

3. 自定义文件描述符
文件描述符时用于访问文件的一个抽象指针。
0,1,2分别是stdin,stdout和stderr的预留描述符

文件描述符有3种使用模式:
▲制度模式
▲截断模式
▲追加模式

创建文件描述符
exec 3 使用文件描述符
echo THIS IS A TEST LINE>input.txt
exec 3 在命令中使用文件描述符:
cat <&3

+++++++++++++++++++++++++++++++++++++++++++
创建一个文件描述符用于写入(截断模式)
exec 4
创建一个文件描述符用于写入(追加模式)
exec 5>>input.txt


1.6 数组和关联数组
普通数组:用整数作为索引

关联数组:用字符串作为索引

普通数组:
定义数组:array_var=(1 2 3 4 5 6)
或者
array_var[0]=”test1”
array_var[1]=”test2”
array_var[2]=”test3”

定义数组:array_var=(1 2 3 4 5)
打印数组中的值:${array_var[0]}
定义变量:index=4
打印对应索引的值:echo ${array_var[$index]}
打印索引的值:echo ${array_var[*]}
打印索引的值:echo ${array_var[@]}
打印数组的长度:echo ${#array_var[*]}


关联数组:(Bash 4.0开始引入)
声明关联数组:declare -A ass_array
向数组中添加元素:
方式一: ass_array=([index1]=val1 [index2]=val2)
方式二: ass_array[index1]=val1
ass_array[index2]=val2

获取数组的索引列表:
echo ${!array_var[*]}
或者
echo ${!array_var[@]}





1.7 使用别名
别名就是一种快捷方式,以省去用户输入一长串命令序列的麻烦

alias new_command=’command sequence’

别名只对当前终端有效,为了使别名一直保持作用,可以将别名写入~/.bashrc中。
echo ‘alias cmd=”cmd sequence” ’ >> ~/.bashrc

删除别名:
可以从 ~/.bashrc文件中进行删除,或者用unalias命令。

例如:创建rm的别名,同时在删除时进行备份
alias rm=’cp $@ ~/backup ; rm $@’

对别名进行转义:(用 \ )
\ command



1.8 获取终端信息
tput 和stty是两款终端处理工具

获取终端的行数和列数:
tput cols
tput lines
设置终端背景色: (no取值0-7)
tput setb no
设置文本前景色: (no取值0-7)
tput serf no

设置文本样式为粗体:
tput bold


2015/5/3 10:57
1.9 获取设置日期和延时
纪元时: 1970年1月1日0时0分0秒所流逝的秒数

命令: date

日期内容 格式
星期 %a (例如:Sat)
%A (例如:Saturday)
月 %b
%B
日 %d
固定格式日期(mm/dd/yy) %D
年 %y
%Y
小时 %I 或%H
分钟 %M
秒 %S
纳秒 %N
UNIX纪元时(以秒为单位) %s


例子:
# date
2015年 04月 22日 星期三 01:11:11 CST
# date +%D
04/22/15
# date +%A
星期三
# date "+%Y %B %d"
2015 四月 22
# date --date "Thu Nov 18 08:07:21 IST 2010" +%s
1290047841
# date -s "21 June 2009 11:01:22"
2009年 06月 21日 星期日 11:01:22 CST


计算命令执行时间:
#! /bin/bash
#检查一组命令所花费的时间
start=$(date +%s)
ls -a
ping 127.0.0.1

end=$(date +%s)
difference=$((end - start))

echo Time taken to execute commans is $difference seconds

也可以用timescriptpath来得到执行脚本所花费的时间


1.9.3补充内容
在脚本中生成延时:
#! /bin/bash
#生成延时
#用tput和sleep从0开始计数到40

echo -n Count;
#存储光标的位置
tput sc

count=0;
while true;
do
if [ $count -lt 40 ];
then let count++;
sleep 3;
#恢复光标位置
tput rc
#清除从当前光标位置到行尾之间的所有内容,使得旧的count值可以被清除并写入新值
tput ed
echo -n $count;
else exit 0;

fi
done


1.10 调试脚本
使用选项 –x,启动跟踪调试shell脚本

set -x : 在执行时显示参数和命令
set +x: 禁止调试
set -v: 在命令进行读取时显示输入
se +v:禁止打印输入

1.0 通过_DEBUG变量来建立调试风格
#! /bin/bash
#debug1.sh
#自定义调试信息
function DEBUG()
{
[ "$_DEBUG" == "on" ] && $@ || :
}


for i in {1..10}
do
DEBUG echo $i
done

执行脚本: _DEBUG=on ./debug1.sh

2.0 使用shebang进行调试
#! /bin/bash -xv

#用shebang自定义调试信息

for i in {1..10}
do
echo $i
done




1.11 函数和参数
[function] fname()
{
echo $1,$2; #访问参数1和参数2
echo “$@”; #以列表的方式一次性打印所有的参数
echo “$*”; #类似于$@,但是参数被看做单个实体
return 0; #返回值
}

1.0 递归函数:
注意: FORK (zhadan)

2.0 导出函数:
函数也可以像环境变量一样用export导出,如此一来,函数的作用域就可以扩展到子进程中。
export –f fname

3.0 读取命令返回值
cmd;
echo $?

$?会给出命令的返回值,成功退出返回0,否则不为0

例如:

#!/bin/bash
#success_test.sh
#测试命令是否成功退出

CMD="ls -a"

status

$CMD

if [ $? -eq 0 ];
then
echo "$CMD executed successfully"
else
echo "$CMD terminated unseccessfully"
fi


4.0 向命令传递参数

1.12 读取命令序列输出
如何组合多个命令以及如何读取其中输出

例如: ls | cat –n > out.txt

方式二:通过子shell的方式读取命令序列
cmd_output=$(ls | cat –n )
echo $cmd_output

方式三:通过反引用的方式也可以用于存储命令输出
例如:
cmd=`ls | cat -n`
echo $cmd

注:反引用与单引号不是一回事,反引用位于键盘的 ~ 键上

1.12.3 补充内容
1.0 利用子shell生成一个独立的进程
子shell本身就是独立的进程,可以使用() 操作符来定义一个子shell。
#! /bin/bash
#子shell生成一个独立的进程

echo -e "打印当前路径\n测试"
pwd;
echo -e "打印目录\n"
(cd /bin; ls);
echo "打印当前路径\n"
pwd;


2.0 通过引用子shell 的方式保留空格和换行符
通过将变量放入双引号中以保留空格和换行符。

#通过引用子shell的方式保留空格和换行符
echo "通过引用子shell的方式保留空格和换行符"
echo "打印a2文件的内容"
cat a2

echo "方式一 会丢失换行符"
out=$(cat a2)
echo $out

echo "方式二 保留换行符"
out="$(cat a2)"
echo $out

经测算:在RedHat5中测试不通过。

1.13 以不按回车的方式读取字符“n”
read命令用于从键盘或标准输入中读取文本。

读取nuber_of_chars个字符
read –n number_of_chars variable_name

◆以不回显的方式读取密码:
read –s var
◆显示提示信息
read –p “Enter input:” var
◆ 在特定时间内读取输入
read –t timeout var
◆用定界符结束输入行
read –d delim_charvar
例如:
read –d “:” var




1.14 字段分隔符和迭代器
内部字段分隔符(Internal Field Separator IFS),可以把单个数据库划分为不同元素的定界符。
用法实例:
# !/bin/bash
#用IFS分割CSV数据

data="name,sex,rollno,localtion"
oldIFS=$IFS
IFS=","
for item in $data;
do
echo Item: $item
done

IFS=$oldIFS


#利用IFS打印用户以及默认shell
line="root:x:0:0:root:/root:/bin/bash"
oldIFS=$IFS
IFS=":"
count=0
for item in $line
do
[ $count -eq 0 ] && user=$item;
[ $count -eq 6 ] && shell=$item;
let count++;
done

IFS=$oldIFS
echo $user\'s shell is $shell;


Bash中各种类型的循环:
◆for循环
◆while循环
◆until 循环

# !/bin/bash
#Bash中的各种循环 for while until

#for循环
for i in {a..z};
do
echo $i
done

#for循环的另一种写法
for((i=0;i<10;i++))
{
echo $i
}


#while循环的用法
echo "while循环的用法"
count=0;
while [ $count -lt 10 ]
do
echo $count;
let count++;
done


#until的用法
echo "until的用法"
x=0;
until [ $x -eq 9 ];
do
let x++;
echo $x;
done


1.15 比较与测试
可用用if, if else 以及逻辑运算符来进行测试。 test命令也可以用来测试。

[ condition ] && action; # &&是逻辑与运算符
[ condition ] || action; #||是逻辑或运算符

[ $var –eq 0 ] 判断条件。 注意空格


算术比较:
其他操作符:
-gt: 大于
-lt: 小于
-ge:大于或等于
-le:小于或等于

[ $var –eq 0 ] # 当var 等于 0 时 返回真
[ $var –ne 0 ] # 当var 不等于 0 时 返回真

[ $var1 –ne 0 –a $var2 –gt 2 ] #使用逻辑与 -a
[ $var1 –ne 0 –o $var2 –gt 2 ] #使用逻辑或 -o

文件系统相关测试:
[ -f $file_var ] :如果既定的变量包含正常的文件路径或文件名,则返回真。
[ -x $file_var ] : 如果既定的变量包含的文件可执行,则返回真
[ -d $file_var ] : 如果既定的变量包含的文件是目录,则返回真
[ -e $file_var ] : 如果既定的变量包含的文件存在,则返回真
[ -c $file_var ] : 如果既定的变量包含是一个字符设备文件的路径,则返回真
[ -b $file_var ] : 如果既定的变量包含是一个块设备文件的路径,则返回真
[ -w $file_var ] : 如果既定的变量包含的文件可写,则返回真
[ -r $file_var ] : 如果既定的变量包含的文件存可读,则返回真
[ -L $file_var ] : 如果既定的变量包含的是一个链接符号,则返回真

例子:
# !/bin/bash
#文件系统相关测试

fpath="/etc/passwd"
if [ -e $fpath ];
then
echo File exists;
else
echo Does not exists;
fi


字符串比较:
使用字符串比较时,最好使用双中括号。采用单个中括号会产生错误。


判断字符串是否相等:
[[ $str1 = $str2 ]]
[[ $str1 != $str2 ]]

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

[[ -z $str1 ]] :如果str1包括的是空字符串则返回真。

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

注意:比较的字符前后都有空格,否则成了赋值语句了。

例子:

#字符串比较
str1="Not empty "
str2=""
if [[ -n $str1 ]] && [[ -z $str2 ]]
then
echo str1 is non-empty and str2 is empty string.
fi


test命令的用法:
test命令可以用来执行条件检测,用test有助于避免使用过多的括号。
例子:
#test命令的用法
var=0
if [ $var -eq 0 ];
then
echo "True";
fi


if test $var -eq 0 ;
then
echo "True";
fi


2015/5/4 1:11

你可能感兴趣的:(Linux,shell,脚本攻略)