Shell脚本入门

GNU bash, version 4.4.23

0、前置知识

01、文本结构

1、脚本文件第一行指定解释器,用#!解释器表示
	如/bin/bash、/usr/bin/python3
2、第二行为注释,用#修饰
3、其他的自由编写,注释也是

02、执行权限

脚本编写完成后会被执行,执行需要权限
0 无权限
1 r 读
2 w 写
4 x 执行
chmod o+x  xx.sh  #添加执行权限 

03、如何执行

脚本文件中已经包含了解释器,权限足够的话,当前目录下直接即可执行
如 ./hi.sh
或者指定编译器bash hi.sh
如果脚本所在的路径存在于环境变量中,那么直接使用文件名即可执行(任意位置)
如hi.sh


#!/bin/bash
# this is shell script,name :hi.sh
echo Hello

./hi.sh即可输出Hello

1、基础语法

1.1、变量

Shell是脚本语言,定义变量比较随意,直接赋值即可,使用的时候,使用$取变量。

关键字readonly、unset用于定义只读和删除变量,local定义局部变量,在函数中演示

#!/usr/bin/bash

myVal="Hello"  --直接定义即可
echo $myVal --使用$获取变量

myVal="World"  --修改变量
echo "$myVal"

readonly myVal="ok" --定义为只读变量
myVal="nice"    --语句非法,无法修改


unset myVal  --删除变量myVal,但是只读变量无法删除,此时报错

1.2、引号

Shell中有单引号、双引号、反引号甚至不加引号

shell中可以不加引号,默认就是字符串

单引号代表不解析,原样输出字符串

双引号解析命令及变量,反引号用于使用命令,可以放在双引号中。

echo `ls` --反引号中使用命令     output:  /  Hi.sh 

echo "当前目录下执行ls命令: `ls`" --将反引号嵌入双引号中 

1.3、字符串

字符串(String)就是一系列字符的组合。字符串是 Shell 编程中最常用的数据类型之一(除了数字和字符串,也没有其他类型了,数组列表之类?)

字符串可以使用{}包裹,用来处理更加复杂的操作,如拼接、截取、长度等

str="Hello Shell"

echo "${str}" #Hello Shell

'#'用来取长度
echo "长度是:${#str}"   #长度是:11

拼接字符串,直接放一起
echo "${str}""dd" 
Hello Shelldd


': :截取字符串,位置:字符个数'
echo "截取字符串:${str:1:5}"
echo "截取字符串:${str::5}"
echo "截取字符串:${str:0-3:5}" 
截取字符串:ello 
截取字符串:Hello
截取字符串:ell

1.4、 $#、$*、$@、$?

Shell脚本执行时经常要从外部传递参数,在文件内部可以使用$接收。

Shell中的特殊字符,$n在文件中指外部参数,0指代本文件名,其他指代参数顺序。

$#指参数数量,$@和$*取所有参数。

$?是上个命令或者函数退出状态

./hi.sh a b c

echo $0   /usr/local/hi.sh
echo $1	 a
echo $2  b
echo $3  c

echo "total num :$#" total num :3
echo "total:$@"  total:a b c


echo $?  0 上个命令正常退出

1.5、数组

Shell 也支持数组,没有限制数组的大小,理论上可以存放无限量的数据,只支持一维数组。

使用x=(z y z)格式声明,使用x[n] 取值

arr=(1 2 3 4 5)
echo "默认从0开始: $arr"
echo "所有值: ${arr[*]}"
echo "数量: ${#arr[*]}"    还是使用'#'获取数量

默认从0开始: 1
所有值: 1 2 3 4 5
数量: 5

arr[6]="ok"
echo "所有值: ${arr[*]}"
所有值: 1 2 3 4 5 ok

unset arr[6] 删除元素
unset arr  删除数组

1.6、(())、流程

shell中的(())用来处理数学运算(let也行),使用if then fi else等关键字处理。

a=20

if ((a>30))
then
    ((a+=10))
    echo $a
elif ((a<10))
then
    echo $a
else
    echo "no"

当然使用:分割后会好看一点
if ((a>30)) ; then
    ((a+=10))
    echo $a
elif ((a<10)) ; then
    echo $a
else
    echo "no" ; fi

shell中的循环使用for控制,可以使用c或者python风格。也有whileunyilselect等循环,1.9中

#c风格的流程
for((i=0;i<10;i++))
do
    echo "C-For: $i"
done



#python风格
for i in 0 2 3 4 5
do
    echo "Python_For :$i"
done

1.7、函数

shell中的函数使用function声明,同样使用$取参数。

调用的时候直接使用函数名即可

function sum() {
    n=0             //这里的变量外部也可以访问,使用local修饰则只能在函数中
    for i in $@
    do
        ((n+=i))
    done
    echo "$n"
}

sum 1 2 3 4  //10
echo $n      //10
sum          //0

echo $? //0 上一个命令或函数退出的状态,正常退出则为0

1.8、read

read 用于从命令行输入,像C的scan,python的input.

参数-p 显示提示信息,-a将数据给数组

read -p "Enter some information > " name url age  //tom 10 www.google.com
echo $name  $age $url     //tom 10 www.google.com


read -a arr      //a b c d

echo ${arr[*]}   //a b c d

1.9、循环

shell中除了for循环外,还有while、until、select in循环以及case in结构

while、until循环

x=8
while ((x<10)) ; do 
    echo "ok"
    ((x+=1))
done       
//ok
//ok

until和 while相反,用一个就行了。

select in循环

select in 循环用来增强交互性,它可以显示出带编号的菜单,用户输入不同的编号就可以选择不同的菜单,并执行不同的功能。
select in 是 Shell 独有的一种循环,非常适合终端(Terminal)这样的交互场景。

arr=("Shell" "Python" "JavaScript")

select x in ${arr[*]};do
    echo "$x"
done
echo "You have selected $x"

1) Shell
2) Python
3) JavaScript 
#? 1               //输入编号
#? Shell
2
Python
#? 3
#? JavaScript
^D           //Crtl+D代表终止,所以上一个就是你的选择

You have selected JavaScript

select in 和用户交互,不会主动终止,使用break让其结束。

case in常和case in 一起用,用来处理条件。

case in )

echo "What is your favourite OS?"
select name in "Linux" "Windows" "Mac OS" "UNIX" "Android"
do
    case $name in
        "Linux")
            echo "Linux是一个类UNIX操作系统,它开源免费,运行在各种服务器设备和嵌入式设备。"
            break
            ;;
        "Windows")
            echo "Windows是微软开发的个人电脑操作系统,它是闭源收费的。"
            break
            ;;
        "Mac OS")
            echo "Mac OS是苹果公司基于UNIX开发的一款图形界面操作系统,只能运行与苹果提供的硬件之上。"
            break
            ;;
        "UNIX")
            echo "UNIX是操作系统的开山鼻祖,现在已经逐渐退出历史舞台,只应用在特殊场合。"
            break
            ;;
        "Android")
            echo "Android是由Google开发的手机操作系统,目前已经占据了70%的市场份额。"
            break
            ;;
        *)
            echo "输入错误,请重新输入"
    esac
done



1) Linux
2) Windows
3) Mac OS
4) UNIX
5) Android
#? What is your favourite OS?
2
Windows是微软开发的个人电脑操作系统,它是闭源收费的。

1.10、test、[[]]

test 是 Shell 内置命令,用来检测某个条件是否成立。test 通常和 if 语句一起使用,并且大部分 if 语句都依赖 test。

test 命令有很多选项,可以进行数值、字符串和文件三个方面的检测。

test 命令比较奇葩,>、<、== 只能用来比较字符串,不能用来比较数字,比较数字需要使用 -eq、-gt
等选项;不管是比较字符串还是数字,test 都不支持 >= 和 <=。有经验的程序员需要慢慢习惯 test 命令的这些奇葩用法。

比较数字

read a

if test $a -eq 10; then
    echo "=10"
elif test $a -gt 10 && test $a -lt 20 ;then
    echo "20>a>10"
elif test $a -le 20 ; then
    echo "<=20"
else
    echo "no"
f

比较字符串

选 项 作 用
-z str 判断字符串 str 是否为空。
-n str 判断宇符串 str 是否为非空。
str1 = str2 str1 == str2 ===是等价的,都用来判断 str1 是否和 str2 相等。
str1 != str2 判断 str1 是否和 str2 不相等。
str1 > str2 判断 str1 是否大于 str2。>>的转义字符,这样写是为了防止>被误认为成重定向运算符。
str1 < str2 判断 str1 是否小于 str2。同样,<也是转义字符。
a=""

if test -z "$a" ; then
    echo "ok"
fi

//ok

比较文件

文件类型判断
选 项 作 用
-b filename 判断文件是否存在,并且是否为块设备文件。
-c filename 判断文件是否存在,并且是否为字符设备文件。
-d filename 判断文件是否存在,并且是否为目录文件。
-e filename 判断文件是否存在。
-f filename 判断文件是否存在,井且是否为普通文件。
-L filename 判断文件是否存在,并且是否为符号链接文件。
-p filename 判断文件是否存在,并且是否为管道文件。
-s filename 判断文件是否存在,并且是否为非空。
-S filename 判断该文件是否存在,并且是否为套接字文件。
文件权限判断
选 项 作 用
-r filename 判断文件是否存在,并且是否拥有读权限。
-w filename 判断文件是否存在,并且是否拥有写权限。
-x filename 判断文件是否存在,并且是否拥有执行权限。
-u filename 判断文件是否存在,并且是否拥有 SUID 权限。
-g filename 判断文件是否存在,并且是否拥有 SGID 权限。
-k filename 判断该文件是否存在,并且是否拥有 SBIT 权限。
文件比较
选 项 作 用
filename1 -nt filename2 判断 filename1 的修改时间是否比 filename2 的新。
filename -ot filename2 判断 filename1 的修改时间是否比 filename2 的旧。
filename1 -ef filename2 判断 filename1 是否和 filename2 的 inode 号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法

[[]][[ ]]是 Shell 内置关键字,它和 test 命令类似,也用来检测某个条件是否成立。
test 能做到的,[[ ]] 也能做到,而且 [[ ]] 做的更好;test 做不到的,[[ ]] 还能做到。可以认为 [[ ]] 是 test 的升级版,对细节进行了优化,并且扩展了一些功能。

a=""

if [[ -z $a ]]; then
    echo "ok"
fi

//ok

[[]]支持正则表达式

a="okok"

if [[ $a=~^o ]]; then
    echo "ok"
fi

原文地址:https://www.cnblogs.com/cgl-dong/p/14052444.html