Shell笔记(2)


Shell 运算符

重点:
	1、在使用! && ||这样符号逻辑连接的时候,尽量使用[[ ]];如果要使用 -a及-o这样字母的逻辑连接时,必须使用[ ]。
	2、单个[ ]使用<、>时一定要加转义符\,不然结果可能不正确,而双[[ ]]是不需要的;特别注意[[ ]]是没有大于等于这种写法的   [[ “abc” < “efg” || “abc” == “abc” ]] 这就做到了<=
	3、a="a" b="a b c"
[[ $a == $b ]]; echo $?     # 得到的是1,没问题
[ $a == $b ]; echo $?   # 这会直接报错,说参数太多,这是因为[]会把$b通过空格分隔开就相当于3个参数了

	4、[[ ]]:无脑使用,无论是整数(全是整数的话还是用(( )),[[]]里面是没有>=、<=的)、小数还是字符串都可以,判定相等有==和=,且不会有单词空格的分割,也不需要转义符号;
	针对字符串还有一个[ ],部分需要转义,有空格分割;
	针对整数还有一个(()),千万别用到字符串比较去了,不会报错,但结构基本都是有问题的,这个判等只有==,在这里=是赋值;
	整数也还能用[ ],它就是搭配字母那种的运算符,如[ 123 -eq 123 ]这样使用。
总之:无论是整数、小数还是字符串,无脑用[[ ]]就对了。但是注意下面一节布尔运算符又要求只能用[ ]。
	5、   [ 1 \> 2 ]; echo $?     # 得1,注意一定要有空格和转义符  **能运行,不会报错

1、预备知识

1、shell支持多种运算符:算数运算、关系运算、布尔运算、字符串运算、文件测试运算
2、expr 是一款表达式计算工具。使用它能完成表达式的求值操作。
3、expr 使用的是反引号
4、表达式和数值 与 运算符之间必须要有空格.2 + 2 ********除了赋值操作,必须没有空格

2、算数运算符

+ - * / %  赋值(=) 
条件表达式:[$a == $b] [$a != $b]
	** 条件表达式必须放在 [] 里面
	** 表达式与运算符之间必须有 空格
	 echo "a+b = `expr 1 + 2 `" 
	** * 运算必须加 \* 才可以实现乘法运算。MAC除外。

3、关系运算符

  • 关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
  • 条件表达式 要用中括号 [ ]
运算符 说明 举例
-eq 相等返回 true [ $a -eq $b ] 返回 false。
-ne 不相等返回 true
-gt 左大右返回 true
-lt 左小右返回 true
-ge 左大等右返回 true
-le 左小等右返回 true
  • 例子
if [ $a -eq $b ]
then
   echo "$a -eq $b : a 等于 b"
else
   echo "$a -eq $b: a 不等于 b"
fi

4、布尔运算符

运算符 说明 举例
! 非运算 [! false] 返回true
-o 或运算
-a 与运算
  • 例子
if [ $a -lt 100 -a $b -gt 15 ]
then
   echo "$a -lt 100 -a $b -gt 15 : 返回 true"
else
   echo "$a -lt 100 -a $b -gt 15 : 返回 false"
fi

5、逻辑运算符

运算符 说明 举例
&& 逻辑AND 前面的错了就不执行后面的了
|| 逻辑OR 前面的对了就不执行后面的了
  • 举例:

     [ 10 -lt 20 ] && [ 1 -gt 2 ] && echo "true" || echo "false"     
     输出:false
     
     ** 多条件的判断可以用[[]] 来括住  echo 不能括。多条件不能用 []来括
      [[ 10 -lt 20 &&  1 -gt 2 ]] && echo "true" || echo "false"   
    

6、字符串运算符

运算符 说明 举例
= 相等返回true [$a = $b] 返回false
!= 不相等返回true
-z 长度为0返回true [-z $a] 返回true
-n 长度不为0 返回true
str 不为空返回true [$a] 返回true

7、文件测试运算符

  • 插播一条文件执行权限:SUID SGID SBIT

    1、suid(set user id): 当s出现在文件所有者的执行位上时,文件调用者暂时获得文件拥有者的权限。Linux的密码机制就是这样。
    -rwsr-xr-x 1 root root 27832 Jun 10  2014 /usr/bin/passwd
    2、sgid(set group id):当s出现在文件所属组的执行权限位时,文件调用者暂时获得所属组的权限。
    3、sbit(Sticky Bit粘滞位):当某一个目录拥有SBIT权限时,则任何一个能够在这个目录下建立文件的用户,该用户在这个目录下所建立的文件,只有该用户自己和root可以删除,其他用户均不可以
    
操作符 说明 举例
-b file 是否是 块设备文件 [-b $file] 返回false
-c file 字符设备文件
-d file 目录
-f file 普通文件(不属于上面两个)
-g file * 是否设置了 SGID位
-k file * 是否设置了粘滞位
-p file 是否是 有名管道
-u file 设置 SUID位
-r file 是否可读
-w file 是否可写
-x file 是否可执行
-s file 是否为空(大小是否大于0)
-e file 是否存在 [-e $file]

实例:

file="/var/www/w3cschool/test.sh"
if [ -r $file ]
then
   echo "文件可读"
else
   echo "文件不可读"
fi
if [ -w $file ]
then
   echo "文件可写"
else
   echo "文件不可写"
fi
if [ -x $file ]
then
   echo "文件可执行"
else
   echo "文件不可执行"
fi

输出命令:Echo 和 Printf

  • echo 用于输出字符串 echo string

1、echo

1、显示普通字符:
	echo "haha"
2、显示转义字符:
	echo "\"haha\""
3、显示变量:
	shell script:
		#!bin/sh
		read name
		echo "$name is ok"
	out:
		input
		inout is ok
4、显示换行:
	echo -e "OK!\n" # -e  开启转义
	echo haha
5、显示不换行:
	echo -e "ok\c" # -e
6、显示结果定向至文件:
	echo "it's a file" > myfile
7、原样输出字符出串:
     echo 'haha"haha"'  '' 里面的任何东西都会原样输出	
8、显示命令执行结果:
	echo `date`      反引号  
	echo `expr 1 + 2`  数字和运算符之间要有空格,= 除外

2、printf

  • 由于模仿 c 语言中的 printf 移植性更好
# format-string为双引号
printf "%d %s\n" 1 "abc"

# 单引号与双引号效果一样 
printf '%d %s\n' 1 "abc" 

# 没有引号也可以输出
printf %s abcdef

# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
printf %s abc def

printf "%s\n" abc def
##格式一样,也会换行
printf "%s %s %s\n" a b c d e f g h i j

# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
printf "%s and %d \n" 
序列 说明
\a 警告字符,通常为ASC|| 的BEL
\b 后退
\ddd 表示1-3位八进制的字符,仅在格式字符串中有效
\0ddd 表示1-3位八进制字符
\c 抑制(不显示)输出结果中任何结尾的换行字符(只在 %b 格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f 换页(fromfeed)
\n 换行
\r 回车(carriage return)
\t 水平制表符
\v 垂直制表符
\\ \

Test与流程控制

1、Test

  • shell test命令用于检查条件是否成立

  • 可进行数值、文字、文件三方面的测试

    1、数值测试

    参数 说明
    -eq
    -ne 不相等
    -gt
    -lt
    -ge 大于等于
    -le 小于等于
    num1=100
    num2=100
    if test $[num1] -eq $[num2]
    then
        echo '两个数相等!'
    else
        echo '两个数不相等!'
    fi
    

    2、字符串测试

    参数 说明
    = 相等则为真
    != 不相等则为真
    -z Str 字符串长度为0 则为真
    -n Str 字符串长度不为0 则为真
    num1="W3Cschool"
    num2="W3Cschool"
    if test num1=num2
    then
        echo '两个字符串相等!'
    else
        echo '两个字符串不相等!'
    fi
    

    3、文件测试

    参数 说明
    -e fileName 文件是否存在
    -r 存在且可读
    -w 存在且可写
    -x 存在可执行
    -s 存在且至少有一个字符
    -d 是目录
    -f 是普通文件
    -c 文件存在且为字符型特殊文件
    -b 存在且为块特殊文件
    if test -e ./bash
    then 
    	echo 'it exist'
    else
    	echo 'it dose not exist'
    fi
    
  • shell 提供了与(-a) 、非(!)或(-o)来将测试条件连接起来。优先级:!> -a > -o

    if test -e ./bin -o -e ./ectt
    then 
    	echo '至少存在一个文件'
    else
    	echo 'they doesn’t exist either'
    

2、流程控制

  • 与java 、php 不同,shell 的流程控制不能为空语句。即:else 语句中不能什么也没有

2.1、if

  • if else

    if condition 
    then 
    	command
    else 
    	command
    fi
    
  • if elif else

    if condition 
    then 
    	command
    elif condition
    then
    	command
    fi
    
  • example

    num1="W3Cschool"
    num2="W3Cschool"
    if test num1=num2
    then
        echo '两个字符串相等!'
    else
        echo '两个字符串不相等!'
    fi
    

2、2 for 循环

  • Base Format

    for var in item1 item2
    do
    	command
    done
    
  • 当变量在列表里面,for 循环执行一次所有命令。使用变量名获取列表中的当前值。命令可为任何有效的shell 命令语句。

  • in 列表里面可以替换字符串、文件名等

  • in 是可以没有的,如果没有的话使用命令行的位置参数

    for i in "haha , big smart"
    do 
    	echo $i
    done
    

2.3、while 语句

  • 基本格式

    while condition
    do 
    	command
    done
    
  • 示例:let"int++" 能完成 int 的自增操作

    #!bin/sh
    int=1
    while (($int<=5))
    do 
    	echo $int
    	let "int++"
    done
    

2.4、无限循环

格式:
while :
do 
	command
done

while true
do 
	command
done

for(( ; ; ))

2.5、until 循环

  • 直到条件为真才停止。

  • 测试条件在最末尾,至少执行一次

    until condition
    do
    	command
    done
    

2.6、case

  • case 语句用来匹配值或者模式。如果匹配成功,执行相匹配的命令。

    case 值 in
    模式1)
    	command1
    	command2
    	;;
    模式2)
    	command1
    	command2
    	;;
    *)
    	command
    	;;
    esca
    
  • example

    echo 'input a Integer from 1 to 4 :'
    read num
    case $num in
    	1|2|3|4) echo "you choose $num"
    	;;
    	*) echo "bad input"
    	;;
    esac
    

2.7、跳出循环

  • break 命令:终止后面的所有循环。

    #!bin/sh
    while :
    do
    	echo -n "输入 1 到 5 之间的数字:"
        read aNum
        case $aNum in
            1|2|3|4|5) echo "你输入的数字为 $aNum!"
            ;;
            *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
                break
            ;;
        esac
    done
    
  • continue:结束本次循环

#!/bin/bash
while :
do
    echo -n "输入 1 到 5 之间的数字: "
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的!"
            continue
            echo "游戏结束"
        ;;
    esac
done