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

【Linux】Shell脚本

文章目录

  • Shell脚本
    • 预备知识
    • 变量
      • 变量作用域
        • export
        • i=10
        • readonly
      • 特殊变量
        • $+数字
        • $#
        • $*
        • $@
    • 运算符
    • 条件判断
      • 大小比较
      • 字符串比较
      • 权限判断
      • 文件类型
      • if语句
      • case
      • for
        • 讲一下前文提到的$* $@
      • while
      • 补充let命令
    • 函数
      • basename
      • dirname
      • 自定义函数
    • 工具
      • cut
      • read
      • sed
      • awk
      • sort

Shell脚本

预备知识

在ubuntu下,/usr/bin/bash存放shell的bash脚本解释器,/usr/bin/bash本质上就是sh的长连接。

使用echo $SHELL可以查看存储脚本的路径的环境变量。

设置脚本文件vim ./mybash.sh先设置一个脚本文件,脚本文件第一行要使用!#/bin/bash表示shell的bash脚本解释器的位置,使用#/bin/sh也一样,目的是为了寻找到脚本解释器的位置。所谓的脚本,就是把多个shell命令,放到一个文件里一起执行。python也有对应的脚本解释器python.exe

执行脚本:如果当前脚本文件有可执行权限,可以直接.mybash.sh执行。第二种方法:使用bash ./mybash.sh执行


变量

在开机后,系统会先从/etc/profile读取全局的系统环境变量信息,然后从~/.bashrc读取用户的系统变量信息,除了环境变量外,还包括命令行解释器、颜色、bash这是从这两个文件下读取配置信息完成初始化的,对于vim,在/etc/.vimrc文件下完成配置,使用set ts=4可以配置Tab键表示4个空格。修改后记得使用source + 指定配置文件完成重新加载。

变量作用域

export
  • Linux 环境变量章节也有讲解,作为内建命令,完成对父进程的环境变量的添加。这里添加的是临时的系统变量,只能在当前会话下有作用,可以交给子进程使用——所以说,如果此时执行bash脚本,可以看到export添加的系统变量,因为bash本来就是一个进程(使用ps命令可以查看bash的进程id,此外,查看时能看到查到的bash 应该名字是--bash,这是因为--bash表示父bash,也就是你当前的命令所处的bash进程,你使用bash test.sh执行脚本时,会添加一个新的bash进程,这个被称为子bash)。
  • 除了export可以设置系统变量外(注意了,只是临时的系统变量,只能在当前会话使用),可以通过修改/etc/profile~/.bashrc来永久添加系统变量,可以在所有会话内使用啦
i=10

如果只是以变量=值的格式设置变量,这个变量是临时的用户变量,只能在当前会话,且当前bash内有效,如果使用bash test.sh运行新的脚本,在新bash不能使用这个变量

readonly

使用readonly修饰变量表示只读,类似const,作用域参考上面两条。

特殊变量

$+数字

在学习cpp java时候我们都知道有一个东西叫做命令行参数,shell脚本也有这个东西,可以使用$1表示传入的第一个参数,$2表示第二个传入的参数

$#

表示传参个数,比如使用bash mybash.sh a b c d此时,echo $#打印4,echo $2打印b

$*

这个变量在for循环处使用样例来讲解

$@

这个变量在for循环处使用样例来讲解


运算符

A=3, B=8, 如果我们希望给D赋值A+B

  • D='expr $A+$B'。这里expr 表示计算,``可以将括住的内容作为一条完成的内容执行,不会截断,并且保留命令结果返回给D
  • D=$[A+B]或者D=$[$A+$B]
  • D=$((A+B))或者D=$(($A+$B))

综合运算

expr `expr 3+5` \* 5 # \*表示转义
echo $[(3+5)*5] #等价

条件判断

大小比较

-lt less than

-le less equal

-eq equal

-ne no equal

-gt greater than

-ge greater equal

字符串比较

=

权限判断

-r -w -x

文件类型

-f 是否是普通文件

-e 是否存在

-d 是否文件存在且文件是目录

if语句

语法格式

if [ 条件表达式 ];then #注意了,[右边有一个空格,]左边有一个空格程序
fi# 或者
if [ 条件判断式 ]then程序
fi

使用样例

# 写一个判断人是否是少年、青年、老年的脚本,通过命令行传参
#!/bin/bashif [ $1 -le 18 ];thenecho "年龄是$1,少年"
elif [ $1 -gt 18 -a $1 -lt 40 ];then # -a表示并且,-o表或者,可以使用[[]]配合&& ||使用,表示 bash 扩展语法,支持 &&/||echo "年龄是$1,青年"
elseecho "年龄是$1,中老年"
fi
~               

case

case $1 in
"start")echo "你写入start"
;; # 等价于其他语言的break
"end")echo "你写入end"
;;
*) # 等价于其他语言的defaultecho "其他"
;;
esac

for

#!/bin/bash# 写一个1+...+100sum=0
for i in {1..100};do # 这个i in {1.100}可以改为((i=1;i<=100;i++))sum=$[sum+i]
doneecho $sum  # 此外,for in的功能十分强大,像是遍历ls结果也可以做到,注意的是,如果文件有空格,就会有问题,因为本质就是通过空格和换行符分隔给不同i
for i in `ls /`;do echo $i
done# 可以通过修改 IFS 变量临时改变分隔符,例如:
# 仅用换行符作为分隔符(忽略空格)
IFS=$'\n'  # 将IFS设为换行符,这里注意,\n和$'\n'不一样,
str="apple banana
cherry  date"for fruit in $str; doecho "水果:$fruit"
doneunset IFS  # 恢复默认IFS
讲一下前文提到的$* $@

代码

#!/bin/bashecho "=== 1. \$* 遍历(不加引号) ==="
for arg in $*; doecho "参数:$arg"
doneecho -e "\n=== 2. \$@ 遍历(不加引号) ==="
for arg in $@; doecho "参数:$arg"
doneecho -e "\n=== 3. \"\$*\" 遍历(加引号) ==="
for arg in "$*"; doecho "参数:$arg"
doneecho -e "\n=== 4. \"\$@\" 遍历(加引号) ==="
for arg in "$@"; doecho "参数:$arg"
done# 执行脚本
# bash ./test.sh "hello world" "foo bar" baz

执行结果

=== 1. $* 遍历(不加引号) ===
参数:hello
参数:world
参数:foo
参数:bar
参数:baz=== 2. $@ 遍历(不加引号) ===
参数:hello
参数:world
参数:foo
参数:bar
参数:baz=== 3. "$*" 遍历(加引号) ===
参数:hello world foo bar baz  # 所有参数合并成一个字符串=== 4. "$@" 遍历(加引号) ===
参数:hello world
参数:foo bar
参数:baz  # 每个参数保持原始格式

关键分析 "$*"

  • 无论传入多少参数,"$*" 都会将它们拼接成一个字符串,拼接符是 IFS 的第一个字符(默认是空格)。例如上面的参数被拼接为 "hello world foo bar baz"

  • for arg in "$*" 遍历时,循环只会执行一次arg 变量的值是整个合并后的字符串(而非逐个参数)。

  • 仅当需要将所有参数作为一个整体处理时使用(例如作为单个字符串传递给其他命令),不适合遍历单个参数。

"$@"

  • 保留每个参数的原始格式(含空格的参数仍作为整体,推荐使用)。

while

i=1
sum=0
while [ $i -le 100 ];dolet sum=sum+ilet i++
done

补充let命令

let 是用于执行算术表达式的命令,可以直接进行整数运算(如加减乘除、自增自减等),并支持变量赋值。

支持基本算术运算与赋值,还有 多个表达式同时执行

a=2
b=3let e=a*b # *不用转义
let "c=a+b, d=a*b"  # 同时计算 c 和 d
echo "c = $c, d = $d"  # 输出:c = 5, d = 6

*支持+±-和+= -= =


函数

basename

basename /usr/bin/a.out .out打印a,其中basename去除前缀,直到最后一个/ 后面的.out表示去除suffix(后缀)

dirname

dirname /home/shell/test01.sh 打印/home/shell 返回是文件所在的目录的绝对路径

实战

#!/bin/bash# 写一个把"./"目录下所有后缀是.txt文件改为.sh后缀dir = "./"
for i in `ls ${dir}*.txt`;dofilename=`basename $i .txt`new_name="${filename}.sh"mv "$i" "$new_name"
done                     

自定义函数

注意的是,如果自定义函数想要return值,只能return 0~255的整数,结果通过echo $?获取

#!/bin/bash
function sum(){let s=$1+$2return $s
}
sum 100 200 # 这里超过了255,会发现返回值不是300.超过这个范围会被取模256.得44
echo $?# 如果希望把更大的结果带出去
function sum2(){let s=$1+$2echo $s
}
result=`sum2 100 200`
echo result

实战

#!/bin/bash# 计算阶乘if [ $# -ne 1 ];thenecho "请输入一个参数即可"exit -1;
fi# 开始主逻辑
function jiecheng(){if [ $1 -le 1 ];thenecho 1 # 当n=1时,返回1,``是把标准输出的结果传出去return 0elif [ $1 -gt 1 ];thenlet prev_n=$1-1tmp=`jiecheng $prev_n`let now=tmp*$1echo $nowreturn 0fi
}jiecheng $1   

工具

cut

cut -d ":" -f1-5 passwd
cut -d ":" -f1,2 passwd
# -d表示分隔符,后面接分隔符。-f表示列数,将指定列打印出来,passwd表示文件,可以使用管道进行读取其他结果# 使用样例
grep "/bin/bash$" passwd | cut -d: -f1 # -d后面可以不加""

read

read -t 3 -p "请在三秒内输入一个大于1的数字: " num # -t 表示最多阻塞时间,-p表示显示提示信息

sed

对输入流(文件或管道数据)进行行级别的编辑(如替换、删除、插入、追加等),其特点是按行处理、默认不修改原文件(除非指定)。

# sed [选项] '命令' 输入文件
# -a add
# -d delete
# -s find and 替换
sed '1a hello world' seg.txt # 在第一行后添加hello world
# 注意,sed只是修改文件缓冲区,不修改文件,加-i选项才会修改文件
sed '/wo/d' seg.txt # 第一个/可以完成查找wo的工作,第二个/分割检索字段和操作字段
sed 's/wo/ni/g' seg.txt # s表示查找并且替换,wo表示谁需要被替换,ni表示替换成ni,g表示宣布替换(如果不添加g,每行只被替换一个)
sed -e '4d' -e 's/wo/ni/g' seg.txt # -e表示在指令生成文本修改,也就是可以同时执行多个指令

awk

# awk [选项参数] '模式{动作}' 输入文件
awk -F: '{print $1 "," $2}' passwd # -F表示切割,$1表示第一列,$2表示第二列
awk -F: '/^laoxiao/{print $1 "," $7}' passwd # ^ 是一个正则表达式元字符,表示 “行的开头”
awk -F: 'BEGIN{print "username, shell"}{print $1 "," $2}END{print "结束"}' passwd # begin表示在最开始先运行,end表示在最后运行

sort

# 默认以字符字典形式排序
# -n 数值大小拍
# -r 相反
# -t 指定分隔符
# -k 列数
http://www.dtcms.com/a/618486.html

相关文章:

  • qt显示类控件---QProgressBar
  • 复式记账的“借”与“贷”
  • 设备健康管理诊断报告生成:工业智能化的“决策引擎”与效率革命​
  • 淘客网站是怎么做的成都网站排名生客seo怎么样
  • vscode插件开发记录
  • 做淘宝代理哪个网站好淘宝网店页面设计
  • 【Linux系统编程】进程控制
  • day2江协科技-3 GPIO
  • Photoshop文字设计基础知识
  • 自己做的网站项目怎样卖微信支付 企业网站
  • Java 大视界 -- Java 大数据机器学习模型在自然语言处理中的少样本学习与迁移学习融合
  • 全椒县城乡建设局网站centos。wordpress
  • 南京华夏商务网做网站怎么样腾讯qq网页版
  • 网站怎么做白色字网站建设和执纪监督
  • Docker使用MinerU
  • 阿里巴巴国际站开店流程及费用福建网站建设
  • 云软件网站建设南昌公司网站建设公司
  • 做一个网站多久沈阳视频制作公司
  • 算法:位运算类型题目练习与总结
  • 中山网站建设中山国产服务器系统免费的有哪些
  • 【水下目标检测】Yolov8-GDFPN实现水下气泡智能识别系统
  • Python转义字符与原字符
  • 双语网站后台怎么做淄博网站快照优化公司
  • 两学一做知识竞答网站越秀营销型网站建设
  • JavaEE ——多线程的线程安全集合类
  • AI重塑语言教育的深层逻辑:从算法到应用的完整旅程
  • 递归算法精讲:从汉诺塔到反转链表
  • 详解 MySQL 自适应哈希
  • 开平市城乡建设局网站电商网站设计公司
  • 【每天一个AI小知识】:什么是支持向量机(SVM)?