`

第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 <<EOF>> 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<input.txt
使用文件描述符
echo  THIS IS A TEST LINE>input.txt
exec 3<input.txt
    在命令中使用文件描述符:
cat <&3

+++++++++++++++++++++++++++++++++++++++++++
创建一个文件描述符用于写入(截断模式)
exec 4<output.txt

创建一个文件描述符用于写入(追加模式)
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


    例子:
    [root@localhost ~]# date
    2015年 04月 22日 星期三 01:11:11 CST
    [root@localhost ~]# date +%D
    04/22/15
    [root@localhost ~]# date +%A
    星期三
    [root@localhost ~]# date "+%Y %B %d"
    2015 四月 22
    [root@localhost ~]# date --date "Thu Nov 18 08:07:21 IST 2010" +%s
    1290047841
    [root@localhost ~]# 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
    分享到:
    评论

    相关推荐

    Global site tag (gtag.js) - Google Analytics