首页 > 系统相关 >Shell笔记:编写脚本常用语法

Shell笔记:编写脚本常用语法

时间:2022-12-27 01:33:08浏览次数:38  
标签:bin ... Shell 变量 笔记 echo 语法 sh 使用

本文记录的是工作中编写脚本的常用语法整理,比较零散,有错欢迎指正。

一、文件第一行

文件的第一行通常为 #!/bin/bash#!/bin/sh#! 用于指定这个脚本文件使用什么解释器来运行,如果在文件第一行指定了解释器,那么直接执行该脚本时就会自动使用文件第一行的解释器来运行该脚本。例如文件test.sh的第一行是 #!/bin/bash ,那么在输入 ./test.sh 后直接回车时(注意,不能直接执行 test.sh ,这种写法会被系统认为你是在执行一个命令,而不是脚本),就会使用 /bin/bash 来运行该脚本。当然,如果输入的是 sh test.sh ,那么第一行的作用就失效了,会使用你手动指定的sh来运行该脚本了。

注: 关于 /bin/bash/bin/sh 的区别,其实 /bin/sh/bin/bash 的软链接,它们对于命令的执行都是一样的。不同之处在于,sh的执行相当于bash的POSIX标准模式,即 /bin/sh 相当于 /bin/bash --posix ,具体的区别体现在sh执行过程中,若出现命令执行失败,则会停止执行脚本,而bash则会跳过失败的命令,继续往后执行。

[root@zjy ~]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 Jan 12  2021 /bin/sh -> bash
[root@zjy ~]# ll /bin/bash
-rwxr-xr-x. 1 root root 1150736 Jan 12  2021 /bin/bash

二、变量

语法:my_var="hello" ,此处定义了一个值为字符串的变量,需要特别注意的是,等号=两边不能有空格。变量的命名只能使用英文字母,数字和下划线,且首个字符不能以数字开头。变量定义之后也可以在其他地方使用同样的语法给它重新赋值,但是注意,不可以使用 $my_var="hi" 这种语法,加花括号是使用变量时才需要的,赋值的时候不可以加花括号。

使用变量: 可以使用两种方式 $my_var${my_var} (推荐),第二种加花括号的目的是帮助解释器识别变量边界,使用第二种方式是一种良好的编程习惯。

删除变量: 使用 unset ${my_var} 即可,删除变量后,再次使用变量不会报错,但是不会有任何值, echo "abc${my_var}def" 输出的值为abcdef。

readonly只读变量: 使用 readonly my_var="hello" 就可以将一个变量设置为只读变量, readonly 关键字也可以在变量定义之后再设置,如 readonly my_var 也是可以的,不是必须在变量初始化的时候才可以设置。当一个变量被设置为只读时,它就不可以被重新赋值,也不可以使用命令 unset 删除。

执行以下脚本 sh test.sh :

#!/bin/sh
readonly my_var="hello"
my_var="hi"

输出为:

[root@zjy ~]# sh test.sh
test.sh: line 3: my_var: readonly variable

三、函数定义

语法如下:

[function] func_name() {
  ...
  [return int]
}

function关键字: 定义一个函数,function关键字是可选的。
语句结束符: 函数中每个语句以换行符作为结束,不用使用分号,一行一句即可,分号通常只是用于连接两个语句。
return关键字: 也是可选的,不指定时自动使用最后一个语句的运行结果作为返回值。
函数返回值: 其实无论是否使用return指定函数返回值,本质上,函数的返回值都是此函数最后一条语句的运行结果。shell中一条语句的运行结果为整数,0表示执行成功,其他数字表示失败。获取函数返回值使用 $?$? 的本质是代表它上一条语句的执行结果,所以函数执行之后想要拿到其返回值, $? 和函数执行语句之间就不能有其他语句的执行。
函数传参: 格式为 func_name var1 var2 var3 ... ,在函数中获取参数时使用 $1${1} 的形式获取对应第一个参数,需要注意的是,获取第十个及以上参数时,就只能使用大括号的格式获取了, $10 是无法获取第十个参数的。

#!/bin/sh
function hello() {
    echo "Hello Shell"
    # 函数参数以$1或${1}、$2或${2}等方式获取对应的第一个、第二个等参数,
    # 如果参数个数大于9,那么从第十个开始,就必须使用${10}的格式了,不能使用$10的格式了
    echo 1
    echo ${2}
    return 0
}

# 函数执行直接将函数名当做命令执行即可,函数参数以空格分隔分别传入
hello var1 var2
# 函数执行结果需要在函数执行之后下一行立马获取,不能有其他语句在这中间去执行,
# 否则$?拿到的就是它上一条语句的执行结果,而不是函数的执行结果了
result=$?
echo ${result}
Hello Shell
var1
var2
0

local变量: local变量就是函数内的局部变量,只能用在函数中,如果在函数之外使用local定义变量,会报错并提示 local: can only be used in a function 。当然,函数内定义的local变量,在函数外就无法使用了,使用时不会报错,只是会拿到一个空的值。

四、if判断

语法如下:

# 单if语句
if condition
then
  command
  ...
fi

# if...else...语句
if condition
then
  command
  ...
else
  command
  ...
fi

# if...elif...else...语句
if condition
then
  command
  ...
elif conditin
then
  command
  ...
else
  command
  ...
fi

分号“;”的使用: 分号并不是语句结束符,它的作用是连接不同的语句,比如想要一个if语句在一行之内编写,可以这样 if condition; then command; fi ,这种使用分号连接多条语句的用法通常用在终端客户端或者临时一次性执行多条语句的时候。在使用if语句的时候,为了编写的shell脚本代码更简洁易懂,我们通常会使用分号将 then 连接在上一行,如:

if condition; then
  command
  ...
elif conditin; then
  command
  ...
else
  command
  ...
fi

五、括号( ) 与 双括号 (( ))

括号( )

单括号 (...) 常用的用法有两种,一种是用于shell中的数组,一种是获取命令执行后的结果。

1. 数组: 括号 ( ) 最直观的使用当然是数组,因为shell中数组的定义就是 array_name=(value1 value2 ...) ,这里只列一些基础的使用示例:

#!/bin/sh

# 数组定义
my_array=("a" "b" "c")
# 根据下标获取数组元素
echo ${my_array[0]}
echo ${my_array[1]}
# 获取数组所有元素
echo ${my_array[*]}
# 获取数组长度
echo ${#my_array[*]}

# 通过下标直接定义数组
new_array[0]="D"
new_array[1]="E"
new_array[2]="F"
# 打印数组所有元素
echo ${new_array[*]}

输出如下:

a
b
a b c
3
D E F

2. 执行命令: 括号 ( ) 另外一种非常常用的用法是使用语法 $(...) 执行命令,然后获取命令的执行结果。

# 执行单个命令
now_date=$(date)
echo ${now_date}

# 多个命令一起执行,获取最后的执行结果
current_path=$(cd $(dirname ${0});pwd)
echo ${current_path}

输出:

Fri Nov 25 01:23:55 CST 2022
/root/shell_test

双括号(( ))

需要特别注意,双括号 (( ))是用于整数运算的,不能用于其他类型数据的运算,并且 (( )) 中使用的变量可以直接使用名称,而不用加 $ 符号。常用的用法有两种,一种是获取整数计算表达式的值,另一种就是作为if语句的判断表达式。

1. 获取整数计算值: 可以使用 $(( ... )) 的方式获取整数计算表达式的值。示例:

#!/bin/sh

a=2
b=3
# 直接使用变量名称进行计算
c=$((a+b))
# 输出结果:5
echo ${c}

2. if条件判断: 作为条件判断时,同样可以使用 +、-、*、/、%、==、!= 等算术运算符,如果想要多个表达式一起判断,也可以使用 &&、|| 逻辑运算符。示例如下:

#!/bin/sh

a=2
b=3
c=6
if ((a<b && a+b<c)); then
    echo "YES"
fi

六、中括号[ ] 与 双中括号[[ ]]

[ ][[ ]] 这两者最常用的用法就是用作条件判断,用作条件判断时, 推荐使用双中括号 [[ ]] 的方式 。需要特别注意,使用时符号边界处和操作符两边都必须要要有空格,如 [[ a > b ]] 。这里列出一些使用它们时的不同之处(了解之后就知道为什么推荐使用 [[ ]] 了):

符号性质

[ ] 是bash的内置命令,而 [[ ]] 是shell编程语言的关键字,它相当于是在 [ ] 命令的基础上进行了扩展, [ ] 可以做到的事情, [[ ]] 几乎都可以做到。

变量引用

[ ] 中使用变量必须加上 $ 符号来引用,否则会报错,而 [[ ]] 不仅兼容 $ 引用的方式,对于数字变量的比较,还可以直接使用变量名进行判断,当然如果变量的值是字符串的话,还是需要使用 $ 进行引用。

a=2
b=3
# 直接使用变量名进行比较判断
if [[ a < b ]]; then
        echo "YES"
fi

关系运算符

对于数字变量的比较,想要使用 “小于”、“大于”等关系运算, [ ] 只能使用 -lt-gt 等字母形式的表示方式,而 [[ ]] 不仅兼容这种方式,还是可以直接使用 <> 等符号的形式。

逻辑运算符

想要使用与、或等逻辑运算关系, [ ] 只能使用 -a-o 等字母的形式,而 [[ ]] 则可以使用 &&|| 等符号表示的方式,但是与前面几种运算符不同, [[ ]] 中不支持使用 -a 等方式的运算。

a=2
b=3
c=6
# 使用$(( ))获取整数运算的结果,再使用&&做逻辑与运算
if [[ a < b && $((a + b)) < c ]]; then
        echo "YES"
fi
# 使用-a做逻辑与运算
if [ ${a} -lt ${b} -a $((${a} + ${b})) -lt ${c} ]; then
        echo "YES"
fi

七、字符串运算

对于字符串的使用,需要加上 $ 进行引用,特别是在 [[ ]] 中作为条件判断时没有使用 $ 的话,无法进行正确的判断。

判断两个字符串是否相同

[[ ]] 使用 ===!= 判断两个字符串是否相等,如果不确定变量的数据类型,但是想要将其转换为字符串再进行比较,可以在变量外边包裹一个双引号再进行判断。

a="abc"
b="bcd"
c="abc"
# 使用=判断字符串是否相等
if [[ ${a} = ${c} ]]; then
        echo "YES-a"
fi
# 使用==判断字符串是否相等
if [[ ${a} == ${c} ]]; then
       echo "YES-c"
fi
# 使用!=判断字符串是否不等
if [[ ${a} != ${b} ]]; then
        echo "YES-b"
fi

d=333
e="333"
# 可以使用双引号将变量包裹起来,将其转换为字符串进行比较判断
if [[ "${d}" == "${e}" ]]; then
        echo "YES-d"
fi

判断一个字符串是否为空(或长度为0)

可以直接对引用的字符串进行判断 if [[ ${var} ]] ,为空就是false,不为空就是true,当然,也可以使用 -z-n 显式的判断字符串是否为空。

a="abc"
b=""
# 使用-z判断字符串是否为空,为空返回true
if [[ -z ${b} ]]; then
        echo "YES-b"
fi
# 使用-n判断字符串是否不为空,不为空返回true
if [[ -n ${a} ]]; then
       echo "YES-a"
fi
# 直接判断引用的字符串是否不为空,不为空返回true
if [[ ${a} ]]; then
        echo "YES-abc"
fi

字符串拼接

拼接字符串最简单的方式就是在外面用一个双引号包裹,里面填充变量值即可。

a="aaa"
b="bbb"
c="ccc"
echo "${a}111${b}222${c}"

标签:bin,...,Shell,变量,笔记,echo,语法,sh,使用
From: https://www.cnblogs.com/guyuyun/p/16891126.html

相关文章

  • 尤克里里指弹教学-趣弹音乐_视频笔记
    尤克里里指弹教学视频地址P2认识四线谱&旅行的意义右手抱琴由上至下,一到四弦表示三张床,每张承受4斤的人数字代表的是品格数,是从琴头到琴尾的格子数持琴方式......
  • 【《硬件架构的艺术》读书笔记】09 电磁兼容性能设计指南(2)
    这一节就大致浏览一下,不细看了。9.6减少EMC/EMI的技术三个方法:1、在源头抑制发射。2、耦合路径尽可能低效。3、受体几乎不受发射影响。9.6.1系统级技术9.6.1.1展频......
  • MarkDown语法
    Markdown学习标题三级标题四级标题 #+空格一级标题##+空格二级标题###+空格三级标题 字体Hello,world!  两边加**表示粗体Hello,world!   两边加......
  • 牛客网刷题笔记篇
    字符串篇字符串翻转链接地址importjava.util.*;publicclassSolution{publicStringtrans(Strings,intn){//writecodehereif(n=......
  • 新概念英语一册语法总结
    目录​​1、简单句的句型结构:​​​​   1-1、简单句​​​​   1-2、句子组织的5步骤:​​​​2、否定句:​​​​3、倒装句(就近原则):​​​​4、一般疑问句:​​​​5......
  • 电脑面试两道问题(python+shell)
    最近面试电脑代码面试遇到两个问题,供大家参考一下一、python脚本:手写一个函数,实现两个数相加,并使用unittest与pytest工具测试函数正确性。1.unnitest进行测试:importun......
  • 网络流24题学习笔记
    前言众所周知,网络流是一种可以解决多种复杂问题的算法,其核心就在于对于问题进行简化并抽象成网络流的一个个模型,再进行求解。本篇则通过网络流24题,网络流中较为经典的题......
  • 【JAVA笔记】JAVA的StringBuilder和StringBuffer类、Data类和Calendar类、基本类型的
    一、StringBuilder和StringBuffer类 实例:packagecn.test02.demo6;publicclassTest1{publicstaticvoidmain(String[]args){//测试构造方法......
  • Python学习笔记--PySpark的相关基础学习(一)
    PySpark包的下载下载PySpark第三方包:构建PySpark的执行环境入口对象PySpark的编程模型数据输入对于SparkContext对象里面的成员方法parallelize,支持:示例:读......
  • 爬虫学习笔记 -- 实战某电影网(lxml库版)
    0x01安装lxml库文件pip3installlxml0x02初始化字符串1、通过HTML类初始化字符串fromlxmlimportetreeimportrequestsurl="https://www.dandanzan10.top/dianying/i......