zoukankan      html  css  js  c++  java
  • 2019年7月23日星期二(shell编程)

    . shell编程的理解?

    1. 什么是shell编程?

    shell编程通过shell语法写出来的文件,这个文件叫shell脚本。例如:Ubuntu中的“~/.bashrc”、开发板中的“/etc/profile”,shell编程有自身独特变量定义,循环结构,分支结构。

    2. 怎么理解shell

    shell在英文中翻译为"贝壳",在贝壳的内部叫内核,在贝壳的外部叫用户,用户与内核之间进行交互必须通过shell来进行解析。

    例子:

       用户                       shell                            内核

      输入ls  ->  ls就是shell命令,使用shell命令解析进行解析   ->  通知内核打印当前目录下所有文件。

    3. 如何解析命令?是谁在解析命令?

    1)解析命令必须有命令行,所以使用命令行之前必须打开一个linux终端,打开一个终端后,会自动运行一个bash进程。因为命令行"gec@ubuntu:~$"就是bash进程打印出来的。

    2)其实就是bash进程在解析命令,也就是说没有命令行,命令是无效。

    4. linux终端、bash进程、shell命令是什么关系?

    gec@ubuntu:~$ ps -ef  -> 查看当前系统中所有进程。

    用户名   进程ID 父进程ID                               进程的名字

    gec       3950     1      0 18:26 ?        00:00:00 gnome-terminal   -> linux终端

    gec       3956  3950      0 18:26 pts/0    00:00:00 bash         -> bash进程,是linux终端的子进程

    gec       4024  3956      0 18:30 pts/0    00:00:00 ps -ef       -> shell命令,是bash进程的子进程

    . shell编程

    1. 什么是shell脚本?

    其实就是使用shell语法组织出来的一个文件,将来运行这个文件,就会依次执行里面每一行的shell语法,这个文件叫称之为shell脚本。

    2. C语言程序与shell编程区别?

                  C语言程序                  shell脚本文件

    ==================================================================      

    语法:            C语言                       shell语法

    是否需要编译: 需要编译器编译            不需要编译,但是必须有解析器

    文件后缀:     xxxx.c                  xxxx.sh

    3. C语言程序与shell编程运行步骤对比:

    C语言:

    1. 创建文件  touch xxxx.c

    2. 编辑程序  gedit xxxx.c

    3. 编译程序  gcc xxxx.c -o xxxx

    4. 执行程序  ./xxxx

    shell

    1. 创建文件  touch xxxx.sh

    2. 编辑脚本  gedit xxxx.sh

    3. 修改脚本权限  chmod 777 xxxx.sh

    4. 执行脚本  ./xxxx.sh

    . shell脚本helloworld程序。

    C语言:

    -----------------------------

    #include <stdio.h>

     

    int main()

    {

           printf("helloworld! ");

           return 0;

    }

    -----------------------------

    shell脚本:

    没有main函数,由于shell中不能调用函数,所以也不需要包含头文件,但是必须要指明一个东西,那么就是/bin/bash。

    1. 怎么指明?

    shell脚本中第1行必须是:  #!/bin/bash   -> 作用: 指明解析器的路径

    2. shell中如何输出字符串到终端上?

    gec@ubuntu:/bin$ man 1 echo

    NAME  -> 对功能进行简单概括

    echo - display a line of text  -> 显示文本

    DESCRIPTION

    Echo the STRING(s) to standard output.  -> 将字符串输出到标准输出上。

    -e     enable interpretation of backslash escapes  -> 解析字符串上的转义符号 

    例子:

    gec@ubuntu:/bin$ echo -e "hello "   -> 加了-e,就会解析

    hello

    gec@ubuntu:/bin$ echo "hello "

    hello

    综上所述,helloworld脚本应该是:

    shell脚本:

    --------------------------------

    #!/bin/bash

    echo "helloworld"

    --------------------------------

    练习1:写一个脚本,要求输出以下的信息。

    1. GZ1934<Tab键>guanguoyuan<Tab键>192.168.90.2

    2. GZ1934

       guanguoyuan

       192.168.90.2

     

    #!/bin/bash

    echo -e "GZ1934 guanguoyuan 192.168.90.2"

    echo -e "GZ1934 guanguoyuan 192.168.90.2"

    . shell脚本的变量定义。

    1. shell语法变量定义规则与C语言一致,只能使用下划线,数字,字母组成,并不能以数字开头。

    2. shell变量不需要声明数据类型,所有变量默认都是字符串类型

    C语言: int a /  char b

    shell: a  -> 默认就是字符串

    3. shell语法中给变量赋值时,等号的两边不允许有空格

    C语言: int a = 100; /  int a=100;  --> OK

    Makefile:  CC = gcc  /  CC=gcc      --> OK

    shell:  a=helloworld  -> OK    a = helloworld  -> Error

    4. shell语法对变量的引用,需要在变量前面添加$

    C语言:

    int a = 100;

    printf("%d ",a);   -> 在C语言中引用变量不需要添加任何符号。

    shell:

    a=helloworld

    echo $a

    例子:

    #!/bin/bash

    str = hello   -> 由于有空格,语法有误。但是不导致程序停止运行。

    echo $str world

     

    5. 变量种类。

    1)自定义变量  str=helloworld

    2)系统环境变量   -> 通过shell命令"env"来查看。

    PWD=/mnt/hgfs/GZ1934/05 shell编程/01/code

    PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/arm/bin:/home/gec/project:/usr/arm/arm-2009q3/bin

    SHELL=/bin/bash

    其中: PWD、PATH、SHELL就是系统的环境变量名字,自定义变量的名字不能与系统环境变量同名。

    3)命令行变量   -> 类似于C语言中argcargv

    C语言:  ./hello aaa bbb

    argc = 3

    argv[0] = "./hello"

    argv[1] = "aaa"

    argv[2] = "bbb"

    shell中也是可以传递参数: ./hello.sh aaa bbb

    $#:  命令行额外(不算"./hello.sh"在内)的参数个数: $#=2

    $1:  第一个额外的参数:  $1=aaa

    $2:  第二个额外的参数:  $2=bbb

    $*:  代表所有的参数    $*=aaa bbb

    $?:  最后一条shell命令执行完的返回值    shell命令执行成功:0  执行失败:非0

    练习2:写出命令行版helloworld脚本。

    #!/bin/bash

    echo $1

    结果:

    ./p2.sh helloworld

    . shell编程符号。

    1. 双引号   -> 作用:将某些东西变成一个""

    1)字符串内部有空格时

    str=helloworld   -> 正确

    str="helloworld"  -> 正确

    当双引号中字符串中没有空格时,加不加双引号。

    str="hello world"  -> 正确

    str=hello world   -> 错误    -> 如果有空格,必须添加双引号。

    2)在""中能不能双引号变量?

    可以使用。

    3)在""能不能用linux命令?

    可以使用,但是命令需要使用反引号(`)标识出来。

    #!/bin/bash

    echo "today is date"   -> 结果: today is date

    echo "today is `date`" -> 结果: today is Mon Jul 22 19:58:15 PDT 2019

    2. 单引号   -> 作用:把单引号括起来的内容看作是一个字符串。

    echo "today is `date`" -> 结果: today is Mon Jul 22 19:58:15 PDT 2019

    echo 'today is `date`' -> 结果: today is `date`

    3. 反引号  ->  作用:把双引号中的命令标识出来。

    echo "today is `date`" -> 结果: today is Mon Jul 22 19:58:15 PDT 2019

    4. 重定位符号 > <

    . 字符串处理

    1. 计算字符串的字符个数

    str=helloworld20helloworld30ashfadsghdcfytzvxcsdhfvtyasdvausd

    echo "${#str}"

    2. 删除字符串左边/右边内容。

    常见shell通配符:  (通用的匹配符号)

    *: 代表任意长度的任意字符。

    ?: 代表一个长度的任意字符。

    [a-z]: 代表一个长度的a-z之间的字符

    [az]: 代表一个长度,只能匹配a/z字符

    [^az]: 代表一个长度,只能匹配除了a或者z之外的字符,与[az]

    #: 从左到右尽可能匹配少的字符

    ##: 从左到右尽可能匹配多的字符

    %: 从右到左尽可能匹配少的字符

    %%: 从右到左尽可能匹配多的字符

    删除字符串左边一些字符,例子:

    str=hello320abc20world

    echo "${str##*20}"   -> 从左到右尽可能多地删除这种"*20"的东西   -> 结果:world

    echo "${str##*[^ac]20}"   -> 从左到右尽可能多地删除  除了*a20/*c20  ->  结果:abc20world

    echo "${str##*[ac]20}"   -> 从左到右尽可能多地删除   *a20/*c20   结果:world

    删除字符串右边一些字符,例子:

    echo "${str%%20*}"  -> 结果: hello3

    echo "${str%20*}"   -> 结果: hello320abc

    练习3:

    str=hello345abcsd3ffworldf45hello123world45hello

    1. 计算字符个数

    2. echo "${str##*3[a-z]}"    orld45hello

    3. echo "${str%3[a-z]*}"   hello345abcsd3ffworldf45hello12

    .测试语句?

    1. 什么是测试语句?

    其实测试就是比较两个值的大小。类似C语言中"=="、"!="、strcmp()

    2. 测试语句需要使用到test命令。  -> man 1 test

    NAME

    test - check file types and compare values  -> 测试文件类型以及比较值。

    SYNOPSIS   -> 使用格式

    test EXPRESSION   等价于   [ EXPRESSION ]

    DESCRIPTION  -> 详细参数描述。

    INTEGER1 -eq INTEGER2

    INTEGER1 is equal to INTEGER2

    INTEGER1 -ne INTEGER2

    INTEGER1 is not equal to INTEGER2

    例子: 测试3是不是等于2

    test 3 -eq 2   等价于   [ 3 -eq 2 ]

    . 分支结构语句

    C语言分支:if-else  switch

    C语言循环:for while do-while

    shell分支:if-else  case

    shell循环:for while until

    1. if-else分支

    框架:

    if 判定条件(测试语句)

    then

           xxxx

    elif 判定条件(测试语句)

    then

           yyyy

    else

           zzzz

    fi

    2. 注意事项:

    1)测试语句的[]的两边不允许有空格。

    2)每一个if语句都会fi作为结束标志。

    3)if后面的判定条件为真(0)时,then后面的语句才会被执行。

    4)else后面是没有then的。

      例题:判断命令行参数是不是为2个,如果不是2个就输出一个字符串报错。

     

    #!/bin/bash

    if [ $# -ne 2 ]

    then

           echo "input arg error"

    fi

    -----------------------

    #!/bin/bash

    if test $# -ne 2

    then

           echo "input arg error"

    fi

    练习4: 使用命令行传递文件名参数,例如: ./xxx.sh 1.txt,如果参数不等于1个,则输出字符串报错。判断该文件是否存在,如果存在,则在终端输出文件的内容,如果文件存在,但是没有读的权限,那么就添加读权限之后,再输出文件的内容,如果文件不存在,则输出字符串"file not exist"这个字符串来报错!

    #!/bin/bash

    if test $# -ne 1

    then

           echo "input arg error"

           exit    -> 直接退出程序

    fi

    if [ -r $1 ]

    then

           cat $1

    elif [ -e $1 ]

    then

           chmod 777 $1

           cat $1

    else

           echo "file not exist"

    fi

    拓展: 使用C语言中完成这道题。

    1. 在程序中如何直接退出程序?  ->  exit()  -> man 3 exit

     

         #include <stdlib.h>

        void exit(int status);

           status: 退出时状态

                   一般正常为0,异常为非0

        返回值:无

    例子: exit(0)  -> 直接正常退出程序

          exit(-1) -> 直接异常退出程序

    2. 判断文件权限以及文件是否存在  -> access()  -> man 2 access

    NAME

    access - check real user's permissions for a file  -> 判断文件权限,以及文件是否存在。

         #include <unistd.h>

       int access(const char *pathname, int mode);

           pathname:需要判断的文件的路径

           mode: F_OK  -> 判断文件是否存在

                  R_OK  -> 判断文件是否存在并可读

                  W_OK  -> 判断文件是否存在并可写

                  X_OK  -> 判断文件是否存在并可执行

           返回值:

                  成功:存在,存在可读,存在可写,存在可执行  -> 0

                  失败:-1

    3. C语言中如何执行linux命令?  ->  system()  -> man 3 system

    NAME

    system - execute a shell command  -> 执行shell命令

           #include <stdlib.h>

          int system(const char *command); 

           command: 需要执行的linux命令

           返回值:

                  成功:0

                  失败:-1

    4. 拼接字符串  -> sprintf()  -> man 3 sprintf

         #include <stdio.h>

       int sprintf(char *str, const char *format, ...);

           str: 缓冲区地址

           format: 格式

           ...: 额外的参数

    argv[1] = "1.txt"

    char buf[50] = {0};

    printf("cat %s",argv[1]);  //将cat 1.txt打印在屏幕上

    sprintf(buf,"cat %s",argv[1]);  //将"cat 1.txt"保存到buf数组中

    参考:

    #include <stdio.h>

    #include <stdlib.h>

    #include <unistd.h>

    #include <strings.h>

    int main(int argc,char *argv[])  //./p4 xxx

    {

           if(argc != 2)

           {

                  printf("input arg error! ");

                  exit(-1);

           }

          

           char buf[50];

           bzero(buf,50);

           if(access(argv[1],R_OK) == 0)  //存在并可读

           {

                  sprintf(buf,"cat %s",argv[1]);

                  system(buf);

           }

           else if(access(argv[1],F_OK) == 0) //存在

           {

                  sprintf(buf,"chmod 777 %s",argv[1]);

                  system(buf);

                  bzero(buf,50);

                  sprintf(buf,"cat %s",argv[1]);

                  system(buf);

           }

           else   //不存在

           {

                  printf("file not exist! ");

           }

          

           return 0;

    }

    2. case分支  -> 针对多种情况

    1C语言中swtich语句框架

    switch(变量)  -> 整型,字符型,枚举类型

    {

           case xx:

                  xxxx;

                  break;

           case yy:

                  yyyy;

                  break;

           default:

                  zzzz;

                  break;

    }

    2shellcase分支框架

    case 变量 in

           xx)   xxxx;;

           yy)   yyyy;;

           *)    zzzz;;

    esac

    拓展:

    C语言从键盘获取整型数据

    int a;

    scanf("%d",&a);

    shell

    read a   -> 阻塞从键盘中获取一个值,存放在a变量中

    gec@ubuntu:/mnt/hgfs/GZ1934/05 shell编程/01/code$ read a

    hello

    gec@ubuntu:/mnt/hgfs/GZ1934/05 shell编程/01/code$ echo $a

    hello

      练习5:执行程序后,从键盘中获取一个值,如果该值为1,则打印one,如果为10,就打印ten,如果都不是,则打印error

    #!/bin/bash

    read a

    case $a in

           1)  echo "one";;

           10) echo "ten";;

           *)  echo "error";;

    esac

      练习6:假设有一个文件名字叫test.txt,内容为10,要求写一个脚本,判断文件的内容

            内容为10,则打印large

            内容为5,则打印middle

            内容为1,则打印small

            其他值,则打印error

           ./test.sh test.txt  --> 要求判断传参问题。

    #!/bin/bash

    if [ $# -ne 1 ]

    then

           echo "input arg error"

           exit

    fi

    val="`cat $1`"

    case $val in

           10) echo "large";;

           5)  echo "middle";;

           1)  echo "small";;

           *)  echo "error";;

    esac

    3. while循环

    1)框架:

    C语言:

    while(判定条件)

    {  //循环体

       ....  -> 循环内容

    }

     

    shell:

    while 判定条件(测试语句)

    do  //循环体

        ....  -> 循环内容

    done

    2shell中整型数据

    str  -> 默认是字符串类型

    declare -i str   -> str就是整型数据

    ----------------------------------------

    #!/bin/bash

    str=100

    str=$str+1

    echo $str  -> 结果: 100+1

    ---------------------------------------

    #!/bin/bash

    declare -i str=100

    str=$str+1

    echo $str  ->结果: 101

    -----------------------------------------

      练习7: 使用while循环打印1~100值。

    #!/bin/bash

    declare -i n=1

    while [ $n -le 100 ]

    do

           echo $n

           n=$n+1

    done

    while循环的死循环:

    #!/bin/bash

    declare -i n=1

    while [ $n -eq 1 ]

    do

           n=1

    done

  • 相关阅读:
    升级系统引起的
    php curl批处理
    看《黑炮事件》想到的
    查找单链表的倒数第k个值
    python绘制树枝
    暑假第九测
    网络流24题(持续更新)
    P2657 [SCOI2009]windy数
    P3177 [HAOI2015]树上染色
    暑假第六测
  • 原文地址:https://www.cnblogs.com/zjlbk/p/11233758.html
Copyright © 2011-2022 走看看