bash编程


先介绍一下什么是shell吧:

壳层在计算机科学中,是指“提供用户使用界面”的软件,通常指的是命令行界面的解析器。一般来说,这


个词是指操作系统中,提供访问内核所提供之服务的程序。Shell也用于泛指所有为用户提供操作界面的


程序,也就是程序和用户交互的层面。因此与之相对的是程序内核,内核不提供和用户的交互功能。 不


过这个词也拿来指应用软件,或是任何在特定组件外围的软件,例如浏览器或电子邮件软件是HTML排版


引擎的shell。Shell这个词是来自于操作系统与用户界面的外层界面。 通常将壳层分为两类:命令行与图


形界面。命令行壳层提供一个命令行界面;而图形壳层提供一个图形用户界面。


bash:据我老师说的,第一次能把Hello world程序成功运行出来,你将会在学习的路上会顺利一点,嘿嘿,有点小迷信了,那么就先从Hello world程序开始吧。

 用vim编辑器编辑hello文件:

 #!/bin/bash

 # This is a simple example

   echp  Hello world

这时候该有同学问#!是什么啊,有什么用,/bin/bash又是什么,

  首先,#! 是说明 hello 这个文件的类型的,有点类似于 Windows 系统下用不同文件后缀来表示不同文件类型的意思(但不相同)。Linux 系统根据 “#!” 及该字串后面的信息确定该文件的类型。


  其次,在 BASH 中 第一行的 “#!” 及后面的 “/bin/bash” 就表明该文件是一个 BASH 程序,需要由 /bin 目录下的 bash 程序来解释执行。BASH 这个程序一般是存放在 /bin 目录下,如果你的 Linux 系统比较特别,bash 也有可能被存放在 /sbin 、/usr/local/bin 、/usr/bin 、/usr/sbin 或 /usr/local/sbin 这样的目录下。


  如何执行该程序呢?有两种方法:一种是显式制定 BASH 去执行:

$ bash hello 或
$ sh hello (这里 sh 是指向 bash 的一个链接,“lrwxrwxrwx 1 root root 4 Aug 20 05:41 /bin/sh -> bash”)

   或者可以先将 hello 文件改为可以执行的文件,然后直接运行它,此时由于 hello 文件第一行的 “#! /bin/bash” 的作用,系统会自动用/bin/bash 程序去解释执行 hello 文件的:

$ chmod u+x hello
$ ./hello

  此处没有直接 “$ hello”是因为当前目录不是当前用户可执行文件的默认目录,而将当前目录“.”设为默认目录是一个不安全的设置。

  需要注意的是,BASH 程序被执行后,实际上 Linux 系统是另外开设了一个进程来运行的。


bash特性之命令别名和命令引用

        alias

alias ALIAS=COMMAND

示例:     

[root@stu31 ~]# alias ls='ls -la'

[root@stu31 ~]# ls /tmp/

total 80

drwxrwxrwt.  5 root root  4096 Aug  3 12:19 .

dr-xr-xr-x. 27 root root  4096 Aug  3 11:12 ..

drwxr-xr-x   2 root root  4096 Jul 28 14:58 dangerous

-rw-------   1 root root     0 Jul 28 10:04 grub-install.img.504t6u

-rw-------   1 root root   401 Jul 28 10:04 grub-install.log.fPXD9g

drwxrwxrwt   2 root root  4096 Aug  3 11:12 .ICE-unix

-rwx------.  1 root root  1118 Jul 28 09:11 ks-script-0C1VlZ

-rwxr-xr-x.  1 root root    67 Jul 28 09:11 ks-script-0C1VlZ.log

drwxr-xr-x   2 root root 53248 Jul 28 14:48 test

-rw-------.  1 root root     0 Jul 28 08:47 yum.log

        别名与命令同名时,要使用绝对路径,\COMMAND生效范围:命令行定义的别名,其生效范围为当前会话;

        

         unalias [ALIAS]

 -a: 撤消所有别名

示例:

[root@stu31 ~]# unalias ls

[root@stu31 ~]# ls /tmp/

dangerous grub-install.log.fPXD9g  ks-script-0C1VlZ.logyum.log

grub-install.img.504t6u  ks-script-0C1VlZ  test

         

          bash支持的引用:

''

""

``:引用一个命令的执行结果

示例:

1alias ls='ls --color=auto' #输出显示为彩色

2[root@stu31 /]# cd `who am i`

 [root@stu31 ~]# 


bash特性之文件名通配(globbing):

            ?:匹配任意字符

            *:匹配任意长度任意字符

             例:*a *b a*b *a*b*

           []:匹配指定范围内的任意单字符

             例:[a-z];[0-9];[a-z0-9]

            [^]:匹配指定范围意外的任意单字符

             例:[^0-9]

             字符集合:                     

                        [:space:] : 所有空白字符

[:punct:] : 所有标点符号

[:lower:] :所有小写字母

[:upper:] :所有大写字母

[:digit:] :所有数字

[:alnum:] :所有大小写字母和数字

[:alpha:] :所有字母

示例:显示/etc目录下,以非字母开头,文件或目录;

# ls -d /etc/[^[:alpha:]]*


bash之快捷键:

        Ctrl+a: 跳转至命令行首

        Ctrl+e: 跳转至命令行尾

        Ctrl+u: 删除命令行首至当前光标所在处之前的所有内容

        Ctrl+k: 删除当前光标所在处至命令行尾的所有内容

        Ctrl+l: 清屏

        Ctrl+c: 中止或取消

        Ctrl+z: 把当命令送至后台


bash之bash变量:

               bash变量类别:

本地变量:只对当前shell进程有效的变量;对其它shell进程无效,包当前                                   shell进程的子进程;

  VAR_NAME=VALUE

  变量赋值:向变量的存储空间保存数据

                                 示例:

                                     [root@stu31 ~]# a=1

                                     [root@stu31 ~]# b=2

                                     

                                     [root@stu31 ~]# echo $a

                                      1

                                     [root@stu31 ~]# echo $b

                                       2

  变量引用:${VAR_NAME}

"":弱引用,里面的变量会被替换;

'':强引用,里面的所有字符都是字面量,直接输出;

                          

                          环境变量:对当前shell进程及其子shell有效,对其它的shell进程无效;

定义:export VAR_NAME=VALUE

导出:export VAR_NAME

用户可自义环境变量

bash有许多内置的环境变量

撤消变量:unset VAR_NAME

只读变量:readonly VAR_NAME


局部变量:

对shell脚本中某代码片断有效;通常用于函数本地;

local VAR_NAME=VALUE


位置变量:

$1, $2, ..., ${10}


                        查看当前shell进程中的所有变量:set

                        查看当前shell进程中的所有环境变量:export, printenv, env

                        变量命名:

               1、不能使用程序中的关键字(保留字);

               比如:if, case, for

               2、只能使用数字、字母和下划线,且不能以数字开头;

               3、要见名知义

                  File


                       变量类型:

                      name=Jerry

                     1、存储机制

                     2、存储空间

                     3、参与的运算方式


                     变量类型:

                     数值型:

                     精确数值:整数

                     近似数值:浮点型

                     单精度浮点

                     双精度浮点

                     字符型:

                           char

                           string

                    布尔型:

                          true, false


                         类型转换:

                         显式转换

                         隐式转换


            bash是弱类型的语言:一切皆字符


bash之bash的配置文件

              profile类:为交互式登录的用户提供配置

      全局:

  /etc/profile

  /etc/profile.d/*.sh

       用户:

  ~/.bash_profile


        功用:

    1、设定环境变量

    2、运行命令或脚本


                bashrc类:为非交互式的用户提供配置

                全局:

            /etc/bashrc

                用户:

            ~/.bashrc


                功用:

            1、设定本地变量

            2、定义命令别名


               登录类型:

                交互式:

                直接通过终端输入账号和密码登录;

               使用su -l USERNAME 或 su - USERNAME;

 

                非交互式:

                 su USERNAME

                 图形界面下打开的终端

                 执行脚本


    通过编辑配置文件修改的配置生效?

      1、退出并重新登录;

      2、让bash重读此配置文件;

. FILE

source FILE


交互登录的用户:

/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc


非交互登录的用户:

~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh


bash之bash编程:

                 特殊变量:

                          $#,$*: 传递给脚本参数的个数

                          $@:引用传递给脚本的所有参数

                          $?:状态返回值

                 bash的循环语句:

                              for

                              while 

                              until

                              for语句格式:

                                          for 变量 in 列表 ;do

                                             执行的命令

                                          done  

                                          (退出条件:遍历结束)  

                             

                           for的第二种使用格式 :

                       for ((初始条件;测试条件;修改表达式)); do

循环体

done

例:for file in `ls`;do echo $file;done

  创建十个文件夹file1-file10                              

#!/bin/bash

for fileName in {1..10};do

touch file$(fileName)
done

计算100以内所有正整数之和
#!/bin/bash
#
declare -i sum=0

for ((counter=1;$counter <= 100; counter++)); do
let sum+=$counter
done
echo $sum

                              

                              while语句格式:                                            

                                                                             while 条件; (注:只要特定条件为真,”while” 语句就会执行)

                                                                             do

                                                                                     语句 

                                                                              done

示例:                                                                                   

#!/bin/bash
COUNTER=0  
while [  $COUNTER -lt 10 ]; do  
    echo The counter is $COUNTER  
    let COUNTER=COUNTER+1   
done

          

                               until语句格式:              

                                                                           until 条件; (注:只要特定条件为假,”while” 语句就会执行)

                                                                             do

                                                                                     语句 

                                                                              done

示例:

#!/bin/bash
myvar=1
until [ $myvar -gt 10 ]do
     echo $myvar
myvar=$(( $myvar + 1 ))
done

              

                              生成列表的方式:

         1、手动给个列表:

    for i in 1 2 3 4 5;

         2、数值列表:

    {start..end}

     `seq [start [increment]] end`

         3、$*, $@

         4 、命令生成列表

示例:

显示/etc/passwd文件中位于文件的第偶数行的用户名;并显示共有多少个这样的用户;
#!/bin/bash
#
totalUsers=`wc -l /etc/passwd | cut -d' ' -f1`

for i in `seq 2 2 $totalUsers`; do
             userName=`head -n $i /etc/passwd | tail -1 | cut -d: -f1`
    echo $userName >> /tmp/passwd.tmp
    echo $userName
done

users=`wc -l /tmp/passwd.tmp | cut -d' ' -f1`
echo "Total users: $users."

 

bash之bash如何实现算术运算:                                                                                          

            变量:弱类型


            如何定义整型变量:

       let VAR_NAME=INTEGER_VALUE

例如:let a=1

        declare -i VAR_NAME=INTEGER_VALUE

例如:declare -i a=3


注意:即使没有定义为整型变量,字符型的数字依然可以参与算术运算;bash会执行变量类型的隐式类型转换;


          实现算术运算的方式:

let VAR_NAME=ARITHMATIC_EXPRESSION

VAR_NAME=$[ARITHMATIC_EXRESSION]

VAR_NAME=$((EXPRESSION))

VAR_NAME=$(expr $num1 + $num2)


算术运算符:

+

-

*

/

%:取模,取余数

5%2=1, 

**: 2**3 (这是次方运算,2的3次方)

示例:
分别计算100以内所有偶数之和和奇数之和;
#!/bin/bash
#
declare -i evensum=0
declare -i oddsum=0

for i in `seq 1 2 100`; do
  oddsum=$[$oddsum+$i]
done

for j in `seq 2 2 100`; do
  evensum=$[$evensum+$j]
done

echo "evensum: $evensum, oddsum: $oddsum."

写一个脚本
1、脚本可以接受一个以上的文件路径作为参数;
2、显示每个文件所拥有的行数;
3、显示本次共对多少个文件执行了行数统计;
4、显示所有文件的总行数;

#!/bin/bash
#
declare -i totalLines=0
declare -i noFiles=0

for file in $*; do
curFileLines=`wc -l $file | cut -d' ' -f1`
echo "$file has $curFileLines."
let noFiles++
let totalLines+=$curFileLines
done
echo "Total Files: $noFiles."
echo "Total Lines: $totalLines."


                        bash弱类型:

                   变量=值

           任何无需事先声明,可直接使用

           值默认都是字符型

           a=abc, b=3

           a=3

           赋值:

       a=4

           增强型赋值:

              +=, -=, *=, /=, %=

              a=$[$a+1] 相当于 let a+=1


自加:var++, var--, ++var, --var

          export PATH=$PATH:/usr/local/apache/bin

          unset: 撤消 

                                算术运算:bash会对数字执行隐式的类型转换

                let VAR_NAME=Integer_Value

                 declare -i Var_Name=Integer_Value


           操作符:

         +, -, *, /, %, **

双目运算符:需要至少两个操作数


              bash的算术运算的方式:

                          let Var_Name=EXPRESSION

                          $[EXPRESSION]

                          $((EXPRESSION))

                          命令:expr ARG1 OP ARG2

例:计算100内的所有正整数的和            
                       #!/bin/bash
                        declare -i sum=0
for i in {1..100}; do
let sum+=$i
done

echo $sum

                      

                  逻辑运算:

                  布尔运算:真,假

                  与、或、非、异或

                  与运算:

                        真,假:

                        真 && 真 = 真

                        真 && 假 = 假

                        假 && 真 = 假

                        假 && 假 = 假


                       或运算:

                         真,假

                         真 || 真 = 真

                         真 || 假 = 真

                         假 || 真 = 真

                         假 || 假 = 假


                         非运算:

                          真,假

                            !真=假

                            !假=真


命令都有其状态返回值:

成功:0,真

失败:1-255, 假

                                    

                          bash条件测试:

                       命令执行成功与否即为条件测试

                test EXPR

                [ EXPR ]

                [[ EXPR ]]


                       比较运算:

                        >, <, >=, <=, ==, !=


            测试类型:根据比较时的操作数的类型

            整型测试:整数比较

            字符测试:字符串比较

            文件测试:判断文件的存在性及属性等


(注意:比较运算通常只在同一种类型间进行)


            整型测试:

              -gt: 大于 

              -lt: 小于

              -ge: 大于等于

              -le: 小于等于

              -eq: 等于

              -ne: 不等于


             字符串测试:

                双目

               >: [[ "$string1" > "$string2" ]]

               <:

               >=

               <=

               ==

               !=


                单目:

                  -n String: 是否不空,不空则为真,空则为假

                  -z String: 是否为空,空则为真,不空则假

    

bash之bash选择:

                

               if: 三种使用格式

           单分支的if语句:

          if 测试条件; then

            选择分支

           fi

表示条件测试状态返回值为值,则执行选择分支;

                           

          双分支的if语句:

          if 测试条件; then

           选择分支1

          else

   选择分支2

           fi

两个分支仅执行其中之一。


                          多分支的if语句:

          if 条件1; then

       分支1

          elif 条件2; then

       分支2

          elif 条件3; then

       分支3

               ...

          else

      分支n

          fi

                    

例:1写一个脚本,接受一个参数,这个参数是用户名;如果此用户存在,则显示其ID号;
      #!/bin/bash
      if ! id $username &> /dev/null; then
    useradd $username
       fi
       
       
           
2通过命令行给定一个文件路径,而后判断:
如果此文件中存在空白行,则显示其空白行的总数;
否则,则显示无空白行;
#!/bin/bash
if grep "^[[:space]]*$" $1 &> /dev/null; then
echo "$1 has $(grep "^[[:space]]*$" $1 | wc -l) blank lines."
else
echo "No blank lines"
fi       
       
       
       
3传递一个用户名给脚本:
如果此用户的id号为0,则显示说这是管理员
        如果此用户的id号大于等于500,则显示说这是普通用户
否则,则说这是系统用户;

#!/bin/bash

if [ $# -lt 1 ]; then
        echo "Usage: `basename $0` username"
        exit 1
fi

if ! id -u $1 &> /dev/null; then
echo "Usage: `basename $0` username"
echo "No this user $1."
exit 2
fi

if [ $(id -u $1) -eq 0 ]; then
echo "Admin"
elif [ $(id -u $1) -ge 500 ]; then
echo "Common user."
else
echo "System user."
fi

                      

                   bash字串测试中的模式匹配:

                    [[ "$var" =~ PATTERN ]]

例:让用户给定一个用户名,判断其是否拥有可登录shell;
#!/bin/bash
#
read -p "Plz input a username: " userName
userInfo=`grep "^$userName\>" /etc/passwd`

if [[ "$userInfo" =~ /bin/.*sh$ ]]; then
echo "can login"
else
echo "cannot login"
fi

                       

bash之case语句:

                 一般,case语句和if一起使用,但是只要你面临可能采取的一系列不同的动作时,你可能迷惑,要处理复杂条件时,你可以考虑一下case语句

                                        case表达式:

                                             case EXPRESSION in 

                                             CASE1) COMMAND-LIST;;

                                             CASE2) COMMAND-LIST;; 

                                              ... 

                                             CASENCOMMAND-LIST;; 

                                             esac

每个分支是一个符合pattern的表达式,在COMMAND-LIST中首先符合的命令就执行该条,没个case语句以esac结束

例:
#!/bin/bash
# 1.) Open file 2.) Display file 3.) Edit file 4.) Delete file
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "---------------------------------"
echo "List of item to operate file -"
echo "---------------------------------"
echo "1). Open a file -"
echo "2). Display a file -"
echo "3). Edit a file -"
echo "4). Delete a file -"
echo "---------------------------------"
read select
case $select in
1)
echo "do open file operation"

2)
echo "do display a file operation"

3)
echo "do edit a file operation"

4)
echo "do delete a file operation"

*)
echo "There is nothing to do!"
exit 1

esac


bash之数组:

          1,声明一个数组

               declare -i array

          2,数组赋值

                (1) array=(a1 a2 a3 ... aN)

              (2)array=([0]=a1 [2]=a2 [3]=a3 ... [n]=aN)

          (3)array[0]=a1  array[1]=a2 array[2]=a3 ... array[n]=aN                               

          3,数组复制:

要使用${ARRAY[@]}

$@: 每个参数是一个独立的串

$*: 所有参数是一个串

               

          4,引用数组

              echo ${array[n]}

          5,数组的访问:

用索引访问:

ARRAY[index]

          6,从数组中挑选某元素:

${ARRAY[@]:offset:number}

切片:

offset: 偏移的元素个数

number: 取出的元素的个数


${ARRAY[@]:offset}:取出偏移量后的所有元素


${ARRAY[@]}: 取出所有元素

  

          7,从数组中删除元素:

              unset ARRAY[index]

例:将字串里的字母逐个放入数组中并输出
#!/bin/bah
chars='qazwsx'
for((i=0;i<=6;i++));do
   array[$i]=${chars:$i:1} (表示从chars字符串的 $i 位置开始,获取 1 个字符)
   echo ${array$[$i]}
done
复制一个数组中下标为偶数的元素至一个新数组中
#!/bin/bash
declare -a mylogs
logs=(/var/log/*.log)

echo ${logs[@]}

for i in `seq 0 ${#logs[@]}`; do
if [ $[$i%2] -eq 0 ];then
index=${#mylogs[@]}
mylogs[$index]=${logs[$i]}
fi
    done

echo ${mylogs[@]}


祝大家看的愉快j_0028.gif



本文出自 “Linux” 博客,转载请与作者联系!

你可能感兴趣的:(编程,bash)