第四章:Shell脚本编程基础

第四章:Shell脚本编程基础

  1. 用户程序不能直接控制计算机硬件,只有操作系统内核才能真正控制计算机硬件

  2. shell本身是一个用C语言编写的程序,他是连接用户和linux/UNIX内核的桥梁。

  3. shell是一个交互式命令解释器,一个读入并解释用户命令的程序

  4. shell同时也是一个程序设计语言,是解释型语言,不需要编译。

  5. shell分为交互式和非交互式

  6. Linux中创建的文件默认是不可执行的,执行脚本首先要赋予文件权限

  7. shell程序第一行#!/bin/bash中#!说明该脚本是用哪一种脚本编写的,从而调用相应的解释程序

  8. 最常见的shell有Bourne shell(简称sh)、C shell(简称csh)、Korn shell(简称ksh)、Bourne-again shell(简称bash)

  9. bash的主要有点:命令记忆功能、自动补全功能、别名设置功能

  10. shell脚本的运行3种方式

    • 首先赋予可执行权限chmod u+x 脚本名然后./脚本名执行程序
    • bash 脚本名将脚本作为参数传递给bash,这种方法不需要在脚本文件第一行指定解释器信息,脚本后面可以带参数
    • bash < 脚本名脚本后面不能带参数
  11. shell特殊字符

    • 通配符

      文件的拓展称为通配

      • *(星号)匹配任意字符0次或多次出现,可以匹配除/之外的任何字符
      • ?(问号)匹配任意单个字符,除/之外
      • [ ] (方括号)匹配该字符组所限定的任何一个字符,[ ]中无论几个字符都只代表一个字符,可以用-指定数字范围
      • [^](音调符号)[!] (感叹号)匹配不在该字符组的任何一个字符
      • {}(大括号){string1、string2 ⋯ \cdots }匹配其中一个指定字符串,该通配符只适用于bash、tcsh不适用于ksh。注意逗号前后不能有空格
    • 引号

      表达特殊字符,用\符号也可达到相同效果,但不易于阅读

      • 单引号:被引号括起来的所有字符都变为普通字符
      • 双引号:被引号括起来的(除$、倒引号`、转义字符\)所有字符都变为普通字符。"$"表示引用变量的值,倒引号代表引用命令
      • 倒引号`:被倒引号括起来的所有字符被shell解释为命令行,shell会先执行改命令、以它的标准输出结果取代倒引号部分
    • 输入/输出重定符号

      标准I/O,shell会自动将程序输入源设置为键盘,称为标准输入;设置程序正确运行的结果输出到显示器,称为标准输出;将程序运行中的错误输出位置也设置为显示器,称为标准错误。标准输入、标准输出、标准错误都以文件的方式存在,缩写为stdin、stdout、stderr。

      类型符号作用
      输入重定向符<file将文件作为命令输入
      输入重定向符<<分界符将文件作为命令输入,直到遇见分界符才停止
      错误输出重定向符2>file以覆盖的方式把错误信息输出到file
      错误输出重定向符2>>file以追加的方式把错误信息输出到file
      输出重定向符>file以覆盖的方式把正确输出到file
      输出重定向符>>file以追加的方式把正确输出到file

      文件描述符,0,1,2分别代表stdin、stdout、stderr

    • 命令执行操作符

      多条命令可以在一条命令中出现,用命令执行操作符连接

      • 顺序执行,命令之间没有逻辑关系,一条报错其他继续执行
      • &&逻辑与,第一条命令正确执行,才会执行第二条命令。%?返回值是0证明执行正确,非零执行错误
      • | |逻辑或,第一条命令执行错误,才会执行第二条命令
    • 小括号和大括号

      • {}在当前shell中执行组命令,左括号{后面有一个空格,右括号}前面有分号
      • ()开启一个子shell执行组命令,不需要空格和分号
    • 管道符、后台命令符、注释符

      • 命令1|命令2管道符,每个命令执行时有一个独立的进程,前一个命令是输出是下一个命令的输入,注意命令1必须正确执行,且输出可被命令2处理
      • &后台命令符,后台进程运行中,与用户无交互(不影响用户输入和中断控制信号),如果后台运行的作业会产生大量的输出,最好把他的输出重定向到某个文件中。
      • #!后面跟解释该脚本的绝对路径,#表示单行注释
  12. Shell编程

    • 变量

      shell变量分为两类:用户自定义变量和系统预定义的特殊变量,所有变量都被视为字符串

      • 用户自定义变量

        • 变量名:变量以字母或下划线开头,由字母、下划线、数字、组成。大写字母通常是系统默认变量,用户自定义变量通常用小写字母
        • 变量赋值:一般形式为变量名=字符串等号两边不能由空格,若出现空格赋值失败,变量依然为空,如果字符串一定要出现空格,要加上引号
        • 变量引用:
          1. 在程序中使用变量值时,要在变量前加“$”,表示使用变量的值
          2. 变量引用存在歧义时,可以用{}""来避免,不可使用$(),$()等价于倒引号
          3. bash仅支持一维数组,元素下标从0开始。数组定义:
            • 一般形式array name=(value1 value2 ... valuen)用括号表示数组,用空格表示分隔符。
            • array name[0]=value1、array name[1]=value2还可以单独定义数组各分量,可使用连续下标,且下标范围没有限制
            • declare -a name declare显示声明一个数组而不赋值
          4. 读数组的格式为${数组名[下标]}如果没有给定下标表示下标为0
          5. ${name[*]}读取整个数组,将数组拓展为一个字符串
          6. ${name[*]}读取整个数组,将数组拓展为多个字符串
      • 系统预定义变量

        预定义变量作用
        $?上一条命令执行后的返回值,大多数shell命令执行后返回值为0
        $$当前进程的进程号
        $!上一个后台命令对应的进程号
        $-当前在运行shell程序的选项
        $nn为数字,$0代表命令本身,$1-9,代表1-9个参数,10以上的参数需要${10}
        $#命令行参数的个数
        $@命令行中的所有参数,每个参数区别对待
        $*命令行中的所有参数,所有参数看成整体

        利用位置参数变量循环的方法:for((i=i;i<$#;i++))while[\$1]配合shiftfor i in "\$@"

        利用set file1 file2赋值把file1赋值给$1,把$赋值给$2

      • 环境变量

        环境变量是系统的预定义变量,是全局变量,在当前shell和所有子shell中都生效

        • HOME:用户家目录绝对路径

        • PATH:shell查找命令的目录列表shell将到哪些目录中查找命令或可执行程序,PATH=$PATH:$HOME/bin在当前查找目录下增加一个目录,$HOME/bin,方便用户使用自建命令。Linux执行程序时在目录下依次查找,所有要注意PATH中的路径顺序

        • PS1:shell的主提示符,shell默认只显示三项\u@\h\W
          \$提示字符,如果是root用户提示符为#,普通用户提示符为$

          \u当前用户名

          \h主机名第一字段

          \W显示完整的工作目录

          \t显示时间为24小时格式

          \T显示时间为12小时格式

          \H显示完整主机名

          \s所用shell名

          \vbash的版本号

        • PWD:当前工作目录的绝对路径

        • SHELL:当前使用的shell,指出它的解释程序在什么位置

        • export 变量名:让自定义变量变为全局变量,可以被子进程继承

      • 变量的查询和删除

        • unset 变量名:注销变量
        • set:查询当前进程下的所有局部变量和全局变量
        • env:查询所有的全局变量
        • export:显示本进程利用export输出的全部变量
    • 数值运算

      shell默认所有的变量都是字符型,所以不能进行数值运算,需要事先声明

      • declare [选项] 变量名

        选项作用
        -给变量设定类型属性
        +取消变量类型属性
        -a将变量声明为数组型
        -i将变量声明为整数型
        -r将变量声明为只读变量,设定完成后不能修改,也不能删除,甚至不能取消只读属性
        -x将变量声明为环境变量,和export作用一样
        -p显示指定变量的类型
      • exprlet命令

        dd=$(expr $aa +$bb):+的左右两边必须有空格

        let dd=$aa+$bb:let命令更简单更常用

      • $((算数表达式))((算数表达式))

        例如dd=$(($aa+$bb)),只有使用$才能返回表达式的值

        常用算数运算符

        优先级运算符作用
        13=赋值
        12||逻辑或
        11&&逻辑与
        10|按位或
        9^按位异与
        8&按位与
        7==,!=等于、不等于
        6<=,>=,<,>小于等于、大于等于、小于、大于
        5<<,>>按位左移、按位右移
        4+,-加、减
        3*,/,%乘、除、取模
        2!,~逻辑非、按位取反、补码
        1+,-单目正、单目负
    • 控制结构

      • if语句

        #if语句一般格式
        #类型一
        if test condition
        	then 命令1
        	else 命令2
        fi
        #类型二
        if [ condition ]                                    #中括号内的每一个组件需要有空格,[]两端也需要空格
        	then 命令1
        	else 命令2
        fi
        #类型三,嵌套
        if [ condition1 ]
        	then 命令1
        	elif [ condition2 ]
        	then 命令2
        	else 命令3
        fi
        

        文件测试运算符

        参数作用
        -r若文件存在且用户可读,测试条件为真
        -w若文件存在且用户可写,测试条件为真
        -x若文件存在且用户可执行,测试条件为真
        -f若文件存在且是普通文件,测试条件为真
        -d若文件存在且是目录文件,测试条件为真
        -b若文件存在且是块设备文件,测试条件为真
        -c若文件存在且是字符设备文件,测试条件为真
        -s若文件存在且文件长度大于0,测试条件为真
        -e该文件是否存在

        字符串测试运算符

        参数作用
        -z s1若字符串长度为0,测试条件为真
        -n s1若字符串长度大于0,测试条件为真
        s1 = s2若s1等于s2,测试条件为真
        s1 != s2若s1不等于s2,测试条件为真

        数值测试运算符

        参数作用
        n1 -eq n2若n1等于n2,测试条件为真
        n1 -ne n2若n1不等于n2,测试条件为真
        n1 -lt n2若n1小于n2,测试条件为真
        n1 -le n2若n1小于或等于n2,测试条件为真
        n1 -gt n2若n1大于n2,测试条件为真
        n1 -ge n2若n1大于或等于n2,测试条件为真
      • case语句

        #case语句一般格式
        case $name in
        	"值1") 命令
        				 命令;;
        	"值2") 命令
        				 命令;;	
        	*) 命令                                                                  #*可缺省
        		命令;;
        esac
        
      • while语句

        执行代码,直到不满足条件才退出

        #while语句一般格式
        #类型一
        while test condition
        do
        	命令循环体
        done
        #类型二
        while [ condition ]  
        do
        	命令循环体
        done
        
      • until语句

        执行代码,直到满足条件才退出

        #until语句一般格式
        #类型一
        until condition                                             #condition部分和if、while一样
        do
        	命令循环体
        done
        
      • for语句

        #for语句一般格式
        #类型一:数值类型循环                                        #与C语言类似
        for ((exp1;exp2;exp3))
        do
        	命令循环体
        done
        #类型二:值类型循环
        for variable in value_list                                      # in value_list 缺省则代表 in $@
        do
        	命令循环体
        done
        
      • select in语句

        交互性循环语句,是无限循环,需要Ctrl+D退出或Break语句。select in 常配合case in一起使用

        #select in语句一般格式
        select  variable in value_list   
        do
        	命令循环体
        done
        
      • break和continue语句

        break n                              #n跳出循环的层数,如果省略表示跳出整个循环
        continue n                       #n跳出本次循环的层数,如果省略表示跳出当前层次循环
        
  13. shell函数

    shell函数定义时不指明参数,使用时可以传递参数,不限制定义和调用的顺序

    #shell函数一般格式
    #类型一
    function name(){
    命令循环体
    [ return value]
    }
    #类型二
    name(){
    命令循环体
    [ return value]
    }
    #类型三
    function name{
    命令循环体
    [ return value]
    }
    
  14. 代码实例1:hello程序

    #!/bin/bash                                                         
    #ShowHello
    #To show hello to somebody
    echo -n "enter your name :"
    read name
    echo "Hello, $name!"
    

    代码实例2:模拟Linux登录shell

    #!/bin/bash         
    echo -n "login:"
    read name
    echo -n "password:"
    read passwd
    if [ $name = "cht" -a $passed = "abc"]
    then echo "the host and password is right"
    else echo "input is error"
    fi
    

    代码实例3:比较两个数的大小

    #! /bin/bash
    echo "please enter two number"
    read a
    read b
    if test $a -eq $b
    then echo "No.1 =No.2"
    elif test $a -gt $b
    then echo "No.1 >No.2"
    else echo "No.1 <No.2"
    fi
    

    代码实例4:查找/root目录下是否存在该文件

    #! /bin/bash
    echo "please enter a file name"
    read a
    if test -e /root/$a
    then echo "the file exists"
    else echo "the file doesn't exists"
    

    代码实例5:for循环的使用

    #!/ bin/bash
    for num in 1 2 3 4 5 6 7 8 9 10
    do 
    echo "$num"
    done
    

    代码实例6:用for循环当前目录下的.c文件移到指定目录下,并按文件大小排序,显示移动后指定目录的内容

    #!/ bin/bash
    echo "input dir"
    read dir
    for file in *.c
    	do
    		cp $file./dir
    	done
    cd $dir
    wc -c * > file1
    sort -n file1
    

    代码实例7:用$RANDOM产生一个随机数,用户猜测,脚本给出提示“大于或小于”,直到用户猜对为止

    #!/ bin/bash
    let num=$RANDOM
    let time=0
    while true
    	do 
    	read -p "please input your guess:" data
    	let time=$time+q
    	if[ $data -eq $num ]
    		then echo "you are right,and you guess $time times"
    	           	  exit 0
    		elif [ $data -gt $num ]
    		then echo "it's high"
    		else  echo "it's low"
    	fi
    	done
    

    代码实例8:测试主机是否在线

    #!/ bin/bash
    ping -c 3 -i 0.2 -W 3 $1 > /dev/null 2 >&1
    if [ $? -eq 0 ]
    	then 
    		echo "$1 is online"
    	else
    		echo "$1 is offling"
    fi
    

    代码实例9:为新用户创建账号和密码

    #!/ bin/bash
    read -p "please input the users's password: " password
    for name in 'cat newuers'
    do 
    	id $name > /dev/null 2 >& 1
    	if [ $? -eq 0 ]
    		then
    		echo "$name already exists"
    		else
    		useradd $name -p $password 2 > /dev/null
    		if [ $? -eq 0 ]
    			then 	echo "$name create success"
    			else 	echo "$name failure"
    		fi
    	fi
    done	
    

    代码实例10:统计指定目录下普通文件,目录文件,链接文件的个数

    #!/ bin/bash
    echo -n "please input the dir"
    read dir
    cd $dir
    echo "the ordinary dile's count is 'ls -l | grep'^-'|wc -l '"
    echo "the directory's count is 'ls -l | grep'^d'|wc -l '"
    echo "the link file's  count is 'ls -l | grep'^l'|wc -l '"
    

    代码实例11:求斐波那契数列的前十项和

    #!/ bin/bash
    i=1
    j=1
    sum=2
    echo $1
    echo $2
    for ((k=0;k<8;k++))
    do
    	let m=i+j
    	let sum=sum+m
    	echo $m
    	i=$j
    	j=$m
    done
    echo $sum
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: APK是安卓应用程序的安装包文件,而执行shell命令是指在安卓系统中运行命令行脚本或者Linux命令的操作。 在APK中执行shell命令可以通过Java的Runtime类和Process类来实现。以下是一个简单的示例: 首先,需要在APK的AndroidManifest.xml文件中添加适当的权限,使得应用程序可以执行shell命令。例如,添加以下权限: <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/> 然后,在APK的Java代码中,可以使用以下代码来运行shell命令: String command = "your_shell_command"; try { Process process = Runtime.getRuntime().exec(command); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); StringBuilder output = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { output.append(line + "\n"); } reader.close(); process.waitFor(); String result = output.toString(); // 处理命令执行的结果 } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } 上面的代码中,先创建一个Process对象,然后通过exec方法执行shell命令。使用BufferedReader读取命令执行结果,并将结果存储在一个StringBuilder对象中。最后,通过调用waitFor方法等待命令执行完成。你可以根据需要,对命令执行结果进行处理。 需要注意的是,在执行shell命令时,可能需要在命令前面加上"su",以获取root权限,从而执行一些需要root权限的命令。 总之,通过在APK中执行shell命令,可以实现一些系统级操作,例如修改系统配置、安装软件、访问设备文件等。但是需要注意的是,使用这种功能需要小心谨慎,确保只执行可信的shell命令,以避免对系统造成损害。 ### 回答2: 在Android开发中,apk是Android应用程序的安装包后缀名。在apk中执行shell命令可以通过Java中的Runtime类实现。 首先,需要在AndroidManifest.xml文件中添加以下权限: ``` <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> ``` 然后,在代码中使用如下方法执行shell命令: ```java try { Process process = Runtime.getRuntime().exec("shell命令"); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); StringBuilder stringBuilder = new StringBuilder(); String line; while ((line = bufferedReader.readLine()) != null) { stringBuilder.append(line); stringBuilder.append("\n"); } String result = stringBuilder.toString(); // 处理命令执行结果 } catch (IOException e) { e.printStackTrace(); } ``` 在exec()方法中传入要执行的shell命令,然后通过BufferedReader读取命令执行的结果,并将结果存储在StringBuilder中。最后可以对结果进行处理。 需要注意的是,执行shell命令可能需要一些特定的权限,例如写入外部存储、读取手机状态等。因此,在使用这种方式执行shell命令时,要确保已经获取了必要的权限,以避免运行时错误。 最后,值得注意的是,在使用apk执行shell命令时,要确保所做的操作符合Android平台的安全策略,以防止不当的使用或滥用。 ### 回答3: APK是Android应用程序包的文件扩展名,它包含了Android应用程序的所有组件和资源。在APK中执行shell命令可以通过使用Android的Runtime类来实现。 要在APK中执行shell命令,首先需要获取Runtime对象,可以使用以下代码: Runtime runtime = Runtime.getRuntime(); 然后,使用该Runtime对象的exec()方法来执行所需的shell命令。以下是一个示例代码: try { Process process = runtime.exec("shell命令"); // 获取命令执行的输入流 InputStream inputStream = process.getInputStream(); // 获取命令执行的错误流 InputStream errorStream = process.getErrorStream(); // 读取输入流和错误流的内容 BufferedReader inputReader = new BufferedReader(new InputStreamReader(inputStream)); BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream)); String line; // 打印命令执行结果 while ((line = inputReader.readLine()) != null) { System.out.println(line); } // 打印错误信息(如果有) while ((line = errorReader.readLine()) != null) { System.out.println(line); } // 关闭输入流和错误流 inputReader.close(); errorReader.close(); } catch (IOException e) { e.printStackTrace(); } 需要注意的是,执行shell命令可能需要相应的权限,因此在执行前需要确保APK的AndroidManifest.xml文件中已经声明了所需的权限。 以上是在APK中执行shell命令的基本步骤和示例代码。通过在APK中执行shell命令,可以实现与系统交互、执行一些系统级操作等功能。但请注意,使用不当可能导致应用程序崩溃或产生安全风险,所以在开发过程中需谨慎使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值