shell 基本语法

这里记录下shell脚本语言的学习

shall是用c语言编写的程序,用于让用户使用Linux,但shall脚本和c的编程格式并不一样

Shall的种类颇多,菜鸟教程里介绍的shall是Bash

唉,大学三年简直白混了,临到毕业疯狂补习基础知识,要不得啊


运行

  1. 添加可执行权限

    $ chmod +x test.sh
    $ ./test.sh
    
  2. 作为解释器参数 $ /bin/sh test.sh


变量

定义变量:等号前后不能加空格 name="myname"

使用变量:echo ${your_name} 花括号可加可不加,但若如同 echo ${your_name}is? ,后面跟字符串或其它内容,而且中间没东西隔开的话一定要加。

只读变量:readonly name

删除变量:unset your_name ,不能删除只读变量

变量类型:

  1. 局部变量
  2. 环境变量
  3. shell变量:由shell程序设置的特殊变量,包含环境变量和局部变量

字符串

单引号、双引号和不加引号都可以定义字符串,但使用场景不同

单引号:所有字符都会原样输出,包括用$表示的变量和转义字符

双引号:里边可以正常显示变量和转义字符

单、双引号里都不允许出现单个的引号,但可以成对出现,代表拼接字符串

str='name'is'yiyuzi'

获取长度:${#str}

提取子串:${string:1:4}

查找子串:查找 i 或 o 最先出现的位置,注意前后是反引号

image-20210305150815779


数组

不支持多维数组,但没有限定数组大小

定义:括号表示,里边用空格隔开,也可以换行隔开,或像c里一样用下标赋值

arr=(v1 v2 v3)

读取元素:${arr[n]}

读取数组所有元素:${arr[@]}

获取数组长度:${#arr[@]}${#arr[*]}

获取单个元素长度:${#arr[n]}


注释

单行注释:行首加 #

多行注释:

  1. 每行前都加#

  2. 把要注释的用花括号括起来,定义成函数,但不调用

  3. :<<EOF
    注释块
    EOF
    
    :<<'
    注释块
    '
    
    :<<!
    注释块
    !
    

传递参数

参数处理 说明
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。 如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ \(*相同,但是使用时加引号,并在引号中返回每个参数。 如"\)@"用「"」括起来的情况、以"$1" "\(2" … "\)n" 的形式输出所有参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

$ chmod +x test.sh 
$ ./test.sh 1 2 3
Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

参数中如果包含空格,应该用引号括起来


运算符

算数运算符:和c一样

关系运算符:不支持字符串

运算符 说明 举例
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。

$a -eq $b

布尔运算符:

运算符 说明 举例
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
-o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。

逻辑运算符:&&和||

字符串运算符:

运算符 说明 举例
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否不相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否不为 0,不为 0 返回 true。 [ -n "$a" ] 返回 true。
$ 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。

文件测试运算符:

操作符 说明 举例
-b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
-d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
-p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
-r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
-w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

echo

会自动添加换行,可以用\c取消


printf

printf 比 echo 的移植性好些

printf不会自动换行

格式化输出的方式和c一样

# 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"


1 abc
1 abc
abcdefabcdefabc
def
a b c
d e f
g h i
j  
 and 0

转义序列:

序列 说明
\a 警告字符,通常为ASCII的BEL字符
\b 后退
\c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f 换页(formfeed)
\n 换行
\r 回车(Carriage return)
\t 水平制表符
\v 垂直制表符
\ 一个字面上的反斜杠字符
\ddd 表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd 表示1到3位的八进制值字符

test

可以检测数值、字符、文件

a=100
b=100
if test $[a] -eq $[b]
then
    echo '两个数相等!'
else
    echo '两个数不相等!'
fi

result=$[a+b] # 注意等号两边不能有空格
echo "result 为: $result"

str1="ru1noob"
str2="runoob"
if test $str1 = $str2
then
    echo '两个字符串相等!'
else
    echo '两个字符串不相等!'
fi

# 另外,Shell 还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低。
if test -e ./notFile -o -e ./bash
then
    echo '至少有一个文件存在!'
else
    echo '两个文件都不存在'
fi

条件控制

if 形如上文,else if 写作elif,可以不换行,写法如下

if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

for var in item1 item2 ... itemN; do command1; command2… done;

while condition
do
    command
done


until [ ! $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done


site="runoob"

case "$site" in
   "runoob") echo "菜鸟教程"
   ;;
   "google") echo "Google 搜索"
   ;;
   "taobao") echo "淘宝网"
   ;;
esac

# 有break和continue

函数

  1. 可以带function fun() 定义,也可以直接fun() 定义,函数体用花括号括起来。

  2. 函数定义不带任何参数,传递参数是用$n。

    注意,$10 不能获取第十个参数,获取第十个参数需要 ​${10}。当n>=10时,需要使用${n}来获取参数。

  3. 参数返回,可以 return 返回,如果不加,将以最后一条命令运行结果,作为返回值。

    函数返回值在调用该函数后通过 $? 来获得。


输出/输出重定向

命令 说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。

posted @ 2021-03-05 16:10  一语子  阅读(227)  评论(0)    收藏  举报