当前位置: 首页 > news >正文

【学习分享】shell脚本基础(全)

Shell

1、基础语法

1.1 变量

1.1.1 规则

与java、python的变量规则一致,大致包含以下规则:

  • 只包含字母、数字和下划线

  • 不能以数字开头

  • 避免使用 Shell 关键字(和其他语言是一样的)

  • 使用大写字母表示常量

  • 避免使用特殊符号和空格

1.1.2 使用

在使用变量前,增加美元符号$

name='zhangsan' 有一个点是需要注意的,python和java当中变量的赋值,等号的左右两边会增加空格去进行区分,但是shell当中不需要,增加了甚至可能报错

echo $name 或者 echo ${name} 本质上两种方式都是一样的,可加可不加,加括号是为了帮助解释器识别变量的边界,但是建议是都加上

1.1.3 只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

这个概念有点像java当中的私有变量,可用 可读,但是无法改变

name="lisi"
readonly name 

这样name这个变量就只读不可用,若强行改变,会报错

1.1.4 删除变量

使用 unset 命令可以删除变量

#!/bin/sh
name="zhangsan"
unset name
echo name
上述代码无任何输出结果
1.1.5 类型
  • 字符串,使用方式和其他语言一样,也是可拼接的,但是有一个需要注意地方,单引号和双引号的区别

    区别单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;单引号字符串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用

    双引号里可以有变量;双引号里可以出现转义字符

    #!/bin/sh
    name=“zhangsan”
    test=“hello,${name}”
    echo test  #输出 hello zhangsan
    test_1='hello,${name}'
    echo test_1  #输出 hello,${name}
    ​
    #获取字符串的长度
    s="test"
    echo $(#s) # 输出4
    ​
    #第二种获取字符串长度的方式
    echo $(#s[0]) # 输出4,本质上当变量为字符串时,${#string} 等价于 ${#string[0]}
    ​
    #查找子字符串
    t="abcdefg"
    echo `expr index "$t" ab` #输出1,输出`ab`这个字符串第一次出现的位置
    ​
    ​

    获取字符串长度

  • 整数变量,和其他语言一样。有个特点是,多了两个关键字“ declare”“typeset ”,这样的声明告诉 Shell 将 my_integer 视为整数,如果尝试将非整数值赋给它,Shell会尝试将其转换为整数

declare -i age=18
  • 数组变量(仅支持一维数组,不支持多维)

aray=(1 2 3 4) #定义数组的形式
#读取数组
s=$(aray[0]) #获取aray数组中的第一个值
​
h=$(aray[@]) # 获取aray数组中的所有值
​
########### 
: '注释'

1.2、参数传递

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为 $nn 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。

例如可以使用 $1、$2 等来引用传递给脚本的参数,其中 $1 表示第一个参数,$2 表示第二个参数,依此类推

 #!/bin/bashecho “$0” #输出脚本名称 包含路径echo "$1" #输出第一个参数 后续的参考上述概念

特殊字符释义:

  • $#:传递到脚本的参数个数(例如:传递的参数为 a b 从,调用该命令,输出3)

  • $*:把所有参数以字符串的形式都传递到脚本

  • $$:脚本运行的当前进程ID号

  • $!:后台运行的最后一个进程的ID号

  • $@:与$*有点相似,在最后具体说明差异

  • $-:显示shell当前选项

  • $?:显示最后命令的退出状态,0表示没有任何错误,其他值是有错误的

$* 与 $@ 区别:

  • 相同点:都是引用所有参数。

  • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。

1.3 数组

1.3.1 数组基础概念

shell的数组命名规则和变一致,格式和主流的编程语言也是一致的,唯一的区别是,数组当中不同的值是用空格隔开的,而非逗号。

#!/bin/bash
array=(1 2 3 4 5 6)
echo $(array[0])  #shell的数组下标也是从0开始而非1,打印第一个数据“1”
1.3.2 关联数组

基础概念:可以使用任意的字符串、或者证书作为下标来访问数组元素。通俗一点的理解就是,普通的数组访问数据内部的元素只能使用下标,且下标只能是阿拉伯数字,关联数组就突破了这个限制,这个“下标”不再是数字,可以是字符串形式。

语法格式:declare -A array_name ,其中-A生命一个关联数组,且键唯一。

#!/bin/bash
declare -A array_test=(["a"]="test1" ["b"]="test2" ["c"]="test3")
echo "打印array_test的值"
echo ${array_test["A"]} #输出test1
echo ${array_test["B"]} #输出test2
echo ${array_test["C"]} #输出test3
echo ${array_test[*]}   #输出test1、test2、test3
echo "打印结束"
​
#也可以先定义,再赋值
declare -A array_test1
array_test1["A"]="kkk"
array_test1["B"]="lll"
array_test1["C"]="JJJ"
echo "开始"
echo ${array_test1["A"]}
echo ${array_test1["B"]}
echo ${array_test1["C"]}
echo "结束"
1.3.3 数组键获取办法

再打印所有值的前面增加感叹号,见以下代码的打印行

#!/bin/bash
declare -A array_test=(["a"]="test1" ["b"]="test2" ["c"]="test3")
echo "打印array_test的值"
echo ${!array_test[*]}   
echo "打印结束"
1.3.4 数组长度获取

再打印所有值的前面增加#,见以下代码的打印行

#!/bin/bash
declare -A array_test=(["a"]="test1" ["b"]="test2" ["c"]="test3")
echo "打印array_test的值"
echo ${#array_test[*]}   
echo "打印结束"

1.4 运算符

1.4.1 算数运算符

和大多数编程语言一样,包含+ 、-、*、/、%、=、==、!= ,具体的可以自己了解。

#原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
#!/bin/bash
val=`expr 1 + 1`
echo "和为:${val}" #输出2
​
val=`expr 1 \* 1`
echo "积为:${val}" #输出1
​
val=`expr 1 - 1`
echo "差为:${val}"
​
val=`expr 8 / 2`
echo "商为:${val}"
​
val=`expr 8 % 3`
echo "余数为:${val}"
1.4.2 关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字

  • -eq:判断两个数是否相等,相等返回true

  • -ne:判断两个数是否不相等,不相等返回true

  • -gt:左边数字是否大于右边,若是,返回true

  • -lt:左边的数字是否小于右边,若是,返回true

  • -ge:左边的数字是否大于等于右边的,若是,返回true

  • -le:左边的数字是否小于等于右边的,若是,返回true

#!/bin/bash
#代码片来自菜鸟编程
a=10
b=20
if [ $a -eq $b ]
thenecho "$a -eq $b : a 等于 b"
elseecho "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
thenecho "$a -ne $b: a 不等于 b"
elseecho "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
thenecho "$a -gt $b: a 大于 b"
elseecho "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
thenecho "$a -lt $b: a 小于 b"
elseecho "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
thenecho "$a -ge $b: a 大于或等于 b"
elseecho "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
thenecho "$a -le $b: a 小于或等于 b"
elseecho "$a -le $b: a 大于 b"
fi
1.4.3 布尔运算符

与或非的运算逻辑与其他的编程语言一致

  • !:运算

  • -o:运算

  • -a:运算

#!/bin/bash
#代码片来自菜鸟编程
a=10
b=20
​
if [ $a != $b ]
thenecho "$a != $b : a 不等于 b"
elseecho "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
thenecho "$a 小于 100 且 $b 大于 15 : 返回 true"
elseecho "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
thenecho "$a 小于 100 或 $b 大于 100 : 返回 true"
elseecho "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
thenecho "$a 小于 5 或 $b 大于 100 : 返回 true"
elseecho "$a 小于 5 或 $b 大于 100 : 返回 false"
fi
1.4.4 逻辑运算符

和布尔有点像,只不过这个是数学中的逻辑符号

  • &&:逻辑的and,全真才为真,一假则假

  • ||:逻辑或,一真则真,全假才为假

#!/bin/bash
#代码片来自菜鸟编程
​
a=10
b=20
​
if [[ $a -lt 100 && $b -gt 100 ]]
thenecho "返回 true"
elseecho "返回 false"
fi
​
if [[ $a -lt 100 || $b -gt 100 ]]
thenecho "返回 true"
elseecho "返回 false"
fi
1.4.5 字符串运算符

这些运算符多用于字符串的操作

  • =:两个字符串如果相等,返回真

  • !=:两个字符串如果不相等,返回假

  • -z:字符串长度为0,则返回真

  • -n:字符串长度不为0,返回真

  • $:字符串内容不为空,返回真

#!/bin/bash
# 代码片来自菜鸟教程
a="abc"
b="efg"
​
if [ $a = $b ]
thenecho "$a = $b : a 等于 b"
elseecho "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
thenecho "$a != $b : a 不等于 b"
elseecho "$a != $b: a 等于 b"
fi
if [ -z $a ]
thenecho "-z $a : 字符串长度为 0"
elseecho "-z $a : 字符串长度不为 0"
fi
if [ -n "$a" ]
thenecho "-n $a : 字符串长度不为 0"
elseecho "-n $a : 字符串长度为 0"
fi
if [ $a ]
thenecho "$a : 字符串不为空"
elseecho "$a : 字符串为空"
fi
1.4.6 文件测试运算符

文件测试运算符用于检测Unix文件的各种属性

  • -b file:若文件是块设备文件,返回true

  • -c file:若文件是字符设备文件,返回true

  • -d file:若文件为目录,返回true

  • -f file:若文件是普通文件,返回true

  • -g file: 若文件设置了SGID位,返回true

  • -k file:若文件设置了sticky bit,返回true

  • -p file:若文件设置了有名管道,返回true

  • -u file:若文件设置了SUDI位,返回true

  • -f file:若文件可读,返回true

  • -w file:若文件可写,返回true

  • -x file:若文件可执行,返回true

  • -s file:若文件部不为空,返回true

  • -e file:若文件存在,返回true

1.4.7 自增/自减

和java等一些主流语言的自增和自减的逻辑是一样的,但是shell使用的是let命令

#!/bin/bash
num=1
let num++
let num++
let num--
echo ${num} # 输出1

1.5 命令

1.5.1 echo命令

该命令用过很多了,用于字符串输出,上述的例子用了很多

#!/bin/bash
echo "hello world" #输出hello word
​
#显示普通字符串,下述两种方式的输出一致
echo "hello world"
echo hello world
​
#显示转义字符
echo "\"hello world"\" # 输出 "hello world"
​
#显示变量
test=33
echo "他的年龄是:${test}" # 输出 他的年龄是:33
​
#显示换行
echo -e "OK \n" # -e 的作用是开启转义
​
#显示不换行
echo -e "OK \c" # -e 开启转义  \c 不换行
​
#显示结果定向至文件
echo "hello world" > file_name
​
#原样输出
echo "$name\" #输出“$name\”
​
#显示命令执行结果
echo `date`
1.5.2 printf命令

printf和大多数的编程语言一样,用于输出,使用该关键字会比echo的移植性更好一些,但是不会想echo自动添加换行符,需要手动添加\n

1.5.2.1 printf格式符:

格式说明符由%开始,后跟一个或者多个字符,用于制定输出的格式,常用的格式说明符:

  • %s:字符串

  • %d:十进制数

  • %f:浮点数

  • %c:字符

  • %x:十六进制数

  • %o:八进制数

  • %b:二进制数

  • %e:科学计数法表示浮点数

#!/bin/bash
printf "hello" #打印hello且不换行
printf "hello\n" #打印hello且换行
​
#printf的实际用法
printf "%-10s %-10s %-10s\n" 你好 我的名字是 张三 #%s是格式代替符号,后续的三个为给代替符号赋值,“-10”标识左边对齐,默认为右对齐,且任何字符都会被显示在10个字符宽的字符内,不足的话则空格补齐
1.5.2.2 printf转义字符

\a:警告字符

\b:后退

\c:抑制输出结果中任何结尾的换行符,旨在%b格式指示符控制下的参数字符串钟有效

\f:换页

\n:换行

\r:回车

\t:水平制表符

\v:垂直制表符

\:一个字面上的反斜杠字符

\ddd:表示1到3位数八进制的字符,仅在格式字符串中有效

1.6 流程控制

shell的流程控制里面无法为空

1.6.1 if else

if的逻辑和java和python1等主流的编程语言一致,只是书写不太相同

#!/bin/bash
#!/bin/bash
a=1
b=2
if (($a > $b))
thenecho "a大"
else    echo "b大"
fi

if else -if else

#!/bin/bash
a=1
b=2
if (($a > $b))
thenecho "a 大"
elif (($a == $b))
thenecho "a b 相等"
elseecho "b大"
fi #放在末尾 结束循环
​
#上述的也可以写成一行,只不过可读性比较差,写成一行的话,需要用分号隔开
​
if [(($a > $b))];then echo "a大";elif [(($a == $b))];then echo "a b 相等";else echo"b大";fi
1.6.2 for循环

for循环的话和其他的编程语言是一致的,关键字和写法有一点区别

#!/bin/bash
for i in 1 2 3 4 5 6 
doecho $i
done #输出 1 2 3 4 5 6
1.6.3 while循环

while循环和主流编程语言的循环是一致的,本身也是死循环,直到不满足循环条件,退出循环

#!/bin/bash
a=0
while (($a < 5))
doecho $alet a++
done 输出0 1 2 3 4 
​
#while循环还可以无限循环 只要循环的条件永远为真
while true #就可以构成无限循环
1.6.4 until 循环

这个和while循环是反过来的,while是条件不再为真的时候停止,而until循环是条件不再为假的时候停止

#!/bin/bash
a=10
until (($a < 3))
doecho $alet a--
done
1.6.5 case esac语句

这个就是switch..case相似的,分支结构的语句

#!/bin/bash
#代码片来自菜鸟编程
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in1)  echo '你选择了 1';;2)  echo '你选择了 2';;3)  echo '你选择了 3';;4)  echo '你选择了 4';;*)  echo '你没有输入 1 到 4 之间的数字';;
esac
1.6.6 总结
shell脚本的循环控制存在跳出指令,break和continue语句,两者的使用区别和使用与java python一致。

区别:break是跳出当前循环,且结束后续循环,continue是跳出当前的此轮循环,但是不停止下一次伦循环。

1.7 函数

函数的定义和javascrip有点类似,直接上例子

#!/bin/bashmyFun(){   #定义一个名称为myFun的函数a=0echo "hello world"  #函数体return $a}echo "begin"myFun  # 函数调用echo $?  #打印函数返回值 也就是函数中的a的值echo "end"

函数的传参形式有点不一样,请看例子

#!bin/bash
myFun(){echo "参数1:$1" #打印参数1echo "参数2:$2" #打印参数2
}
myFun 10 11 #调用函数 并且输入参数1和2 分别为10 和11

1.8 shell输入/输出重定向

输入输出的重定向,比较简单的理解就是,改变脚本的输入和输出方向。正常来说,使用终端运行脚本,会将最终结果显示在终端,输出重定向后,输出会保存到指定的文件当中,输入重定向亦是如此。

命令说明
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 之间的内容作为输入。

直接上代码

#!/bin/bash
#创建目标txt文件夹
​
echo "hello world"<log.txt #输出将打印在log.txt当中
​
echo "happy"<<log.txt #输出将接在hello world下面 若是"<" 则是覆盖
​
#同理,输入重定向
cat data.txt #读取该文档的内容
read a < data.txt #读取该文件数据
echon "获取的数据是:$a" #输出

一般情况下,每个 Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。

  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。

  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

#!/bin/bash
​
fun 1 2 3 2>errorlog.txt #调用未定义的函数fun并赋值,程序会报错,且报错信息会谢若errorlog文件当中
​
echo "正常输出" 2>errorlog.txt #输出正常值,errorlog文件不会出现运行结果
​
#如果要将正常输出和非正常输出都放在一个文件,可以有下面的写法
myFun(){echo "正常输出" fun
}>log.txt 2>&1
myFun  #输出内容为:“正常输出” 报错信息“未找到命令”

http://www.xdnf.cn/news/959167.html

相关文章:

  • 深度解析云存储:概念、架构与应用实践
  • 外链域名年龄 vs 数量老域名的1个链接抵新域名的100个吗?
  • 【配置篇】告别硬编码:多环境配置、@ConfigurationProperties与配置中心初探
  • FDD损失函数 损失函数和梯度的关系
  • Day49 Python打卡训练营
  • 【前端】js Map集合的使用方法
  • C++11委托构造函数和继承构造函数:从入门到精通
  • 查询宝塔的数据库信息
  • 共享存储系统
  • 动画直播如何颠覆传统?解析足球篮球赛事的数据可视化革命
  • ONNX详解:跨平台模型部署解决方案
  • 【Java】谈谈HashMap
  • 2025.06.09【RNA-seq】|逆转录元件(retrotransposon)表达分析全流程详解
  • 运动控制--小车的启动和停止算法
  • 数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
  • 数据集转换xml2txt 、xml2json、json2coco
  • 重排和重绘是什么,怎么解决?
  • GruntJS-前端自动化任务运行器从入门到实战
  • CAR:推理长度自适应新框架,提升精度同时还降低推理token数!!
  • python爬虫之数据存储
  • LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《一》
  • 视频监控厂商“以图搜图”能力比对(大华/海康)
  • Java数值运算常见陷阱与规避方法
  • 华为WLAN概述知识点及案例试题
  • day26/60
  • java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
  • 项目课题——基于LoRa的农业环境监测节点
  • GC-QA-RAG 智能问答系统的问答生成
  • Spring Bean的初始化过程是怎么样的?​​
  • ROS mapserver制作静态地图