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

超详细介绍bash脚本相关细节

        Bash(Bourne Again SHell)是一种广泛使用的Unix shell和命令语言,它提供了一套强大的功能用于脚本编写和自动化任务。

1.编写脚本方式和运行脚本方式

sudo vi 名称.sh
  • 例如编写 一个名称为a的脚本:

运行方式1:先给权限再运行

 sudo chmod +x 文件名
./文件名
  • 例如创建一个a.sh的脚本并给他执行的权限

(1)在终端输入下面的代码后enter

 sudo vi a.sh

(2)点击 i 进入插入模式,输入以下内容

(3)按esc键退出插入模式,输入“: wq” 保存并退出

(4) 使用命令ll 查看发现a.sh文件没有执行权限

(5)使用下面的命令给a.sh文件加执行权限

sudo chmod +x a.sh

结果如下: 

 

(6)使用./a.sh就可以执行文件

运行方式2:直接  bash 文件名 

(1)先将可执行脚本文件去除执行权限

(2)使用 bash ./a.sh 

运行方式3:直接 sh 文件名

结果如下:

 


2. 脚本开头

        每个 Bash 脚本都应该以一个 “shebang” 开头,后跟解释器的路径。这告诉系统应该使用哪个解释器来执行这个脚本。

#!/bin/bash

3. 变量

(1)在 Bash 脚本中,变量不需要声明,但赋值时不能在变量名和值之间加空格。

a="Hello, World!"

如下图的变量b: 

 

运行结果如下:

(2)要引用变量,需要在变量名前加上美元符号$

echo $a

或者用花括号来明确变量的边界:

echo ${a}

(3)可以将变量设置为只读,这意味着该变量的值不能更改。(类似Java中的常量)

variable="Hello, World!"
readonly variable
# 下面的赋值会失败
variable="Goodbye, World!"  # 报错:variable 只读变量

运行结果如下:  

补充:也不能使用unset

 

 运行结果如下: 

(4)环境变量是全局变量,它们会影响当前shell及其子shell的执行环境。

export 变量名="路径"
1.首先我们要到/etc/profile文件中添加全局变量
sudo vim /etc/profile
2.进入之后光标移动到最底部点击 i 进入插入模式,添加环境变量(例如:MY_NAME="/home/tom")
export MY_NAME=/home/tom

3.输入后,按esc键再输入“: wq”保存并退出
4.输入source /etc/profile   当你执行 source /etc/profile 命令时,你实际上是在告诉shell:“现在,我想重新读取并执行 /etc/profile 文件中的所有命令,以便更新我的环境变量和其他设置。”
source /etc/profile
5.编写一个Shell脚本

运行结果如下:

(5)bash提供了一些特殊变量,例如:

  • $0 - 脚本名称
  • $1 - 脚本的第一个参数
  • $2 - 脚本的第二个参数
  • $# - 传递给脚本的参数个数(${#变量名} - 变量的长度)
  • $* - 所有位置参数的单个字符串
  • $@ - 所有位置参数的单独引用字符串
  • $? - 最后一条命令的退出状态
  • $$ - 当前shell进程ID(PID)
  • $! - 最后一个后台命令的进程ID

运行下面代码的注意要传两个参数:(这里我的脚本名字是a,传的参数是10和20)

./a.sh 10 20
#!/bin/bash
echo "Script name: $0"
echo "First argument: $1"
echo "Second argument: $2"
echo "Total number of arguments: $#"
echo "All arguments as a single string: $*"
echo "All arguments as separate strings: $@"
echo "Exit status of last command: $?"
echo "Process ID of current shell: $$"

4. 注释

注释以#开头,用于解释脚本中的代码。

# 这是一个注释

5. 输入输出重定向

可以使用><符号来重定向输入输出。

echo "This will be saved in a file." > output.txt
cat < input.txt

6.数学运算

(1)使用 $((...)) 进行算术

#!/bin/bash

# 定义变量
a=5
b=3

# 加法
sum=$((a + b))
echo "Sum: $sum"

# 减法
diff=$((a - b))
echo "Difference: $diff"

# 乘法
product=$((a * b))
echo "Product: $product"

# 除法(整数除法)
quotient=$((a / b))
echo "Quotient: $quotient"

# 取余数
remainder=$((a % b))
echo "Remainder: $remainder"

如果你想要动态输入变量将变量a换成$1,将变量b换成$2即可

#!/bin/bash
# 加法
sum=$(($1 + $2))
echo "Sum: $sum"

(2)使用 $[...] 进行算术

#!/bin/bash

# 定义变量
a=10
b=3

# 加法
sum=$[a + b]
echo "Sum: $sum"  # 输出: Sum: 13

# 减法
diff=$[a - b]
echo "Difference: $diff"  # 输出: Difference: 7

# 乘法
product=$[a * b]
echo "Product: $product"  # 输出: Product: 30

# 除法(整数除法)
quotient=$[a / b]
echo "Quotient: $quotient"  # 输出: Quotient: 3

# 取余数
remainder=$[a % b]
echo "Remainder: $remainder"  # 输出: Remainder: 1

# 使用赋值运算符进行自增
a=$[a + 1]
echo "a after increment: $a"  # 输出: a after increment: 11

# 使用赋值运算符进行自减
b=$[b - 1]
echo "b after decrement: $b"  # 输出: b after decrement: 2

(3)let 命令可以在Bash中执行算术运算,并更新变量的值。

#!/bin/bash

# 定义变量
a=5
b=3

# 使用let进行加法
let sum=a+b
echo "Sum: $sum"

# 使用let进行减法
let diff=a-b
echo "Difference: $diff"

# 使用let进行乘法
let product=a*b
echo "Product: $product"

# 使用let进行除法(整数除法)
let quotient=a/b
echo "Quotient: $quotient"

# 使用let进行取余数
let remainder=a%b
echo "Remainder: $remainder"

7. 控制流

(1)单分支if 语句

语法格式:

if 条件测试表达式;then
操作语句(可以多条)
fi

1.[ ]命令类型

#!/bin/bash

number=10

if [ $number -gt 5 ]; then
  echo "Number is greater than 5."
fi

        在这个例子中,我们定义了一个变量 number 并赋值为 10。if 语句检查 number 是否大于 5。如果条件为真,则执行 then 后面的代码块,输出 “Number is greater than 5.”。

2. test 命令类型

test 命令可以用来执行条件测试,它与 [] 的用法基本相同,但是不需要括号。

#!/bin/bash

file="test.txt"

if test -e "$file"; then
  echo "File exists."
else
  echo "File does not exist."
fi

3. 双中括号 [[ ]]类型

        双中括号 [[ ]] 提供了更强大的模式匹配功能,并且允许使用正则表达式。它通常用于更复杂的条件测试。

#!/bin/bash

string="Hello World"

if [[ $string == *"World"* ]]; then
  echo "The string contains 'World'."
fi

在 [[ ]] 中,可以使用 == 来比较字符串,并且可以使用通配符,如 *

4. 双括号 (( ))类型

双括号 (( )) 用于执行算术比较和赋值。它允许在比较中使用高级数学表达式。

#!/bin/bash

num=10

if (( num > 5 )); then
  echo "The number is greater than 5."
fi

# 在双括号内也可以进行赋值和算术运算
(( num++ ))
echo "The number is now $num."

在 (( )) 中,不需要在变量名周围使用引号,也不需要在操作符周围加空格。

注意事项

  • [ 和 ] 是测试命令的符号,与 test 命令等价。
  • [ 命令和要测试的变量或表达式之间必须有空格。
  • 在使用 [ 命令时,变量不需要使用 $ 符号。
  • 在使用 [[ 双方括号时,支持更多的模式和操作,并且不需要空格分隔。
表达式类型语法支持的操作符特点与限制整数比较符字符串比较操作符
test 命令test expression文件测试(如 -e-d)、字符串比较(如 =!=)、整数比较(如 -eq-lt传统的条件测试命令,返回退出状态(0为真,非0为假)-eq(等于)、-ne(不等于)、-lt(小于)、-le(小于等于)、-gt(大于)、-ge(大于等于)=、==、!=
[](测试表达式)[ expression ]与 test 命令相同test 命令的简写形式,需要注意特殊字符的转义-eq(等于)、-ne(不等于)、-lt(小于)、-le(小于等于)、-gt(大于)、-ge(大于等于)=、==、!=
[[]](扩展的测试表达式)[[ expression ]]支持字符串模式匹配(如 *?)、逻辑运算符(如 &&, ||)[[]] 提供了比 [] 更强大的测试功能,包括支持字符串模式匹配(使用 * 和 ?)、逻辑运算符 && 和 || 无需转义、以及更复杂的表达式评估。-eq(等于)、-ne(不等于)、-lt(小于)、-le(小于等于)、-gt(大于)、-ge(大于等于)<(小于)、<=(小于等于)、>(大于)、>=(大于等于)、==(等于)、!=(不等于)=、==、!=
(())(算术表达式)(( expression ))算术运算符(如 +-*/%)、整数比较(如 <><=>=用于执行算术计算和比较,返回算术结果(可用于条件语句中的算术比较)<(小于)、<=(小于等于)、>(大于)、>=(大于等于)、==(等于)、!=(不等于)=、==、!=

 (2)多分支if-elif-else 语句

语法格式:

if 条件测试表达式;then
操作语句1(可以多条)
elif 条件测试表达式;then
操作语句2(可以多条)
else 
操作语句3(可以多条)
fi
#!/bin/bash

number=7

if [ $number -gt 10 ]; then
  echo "Number is greater than 10."
elif [ $number -gt 5 ]; then
  echo "Number is greater than 5 but not greater than 10."
else
  echo "Number is not greater than 5."
fi

        这里我们使用了 elif(else if的简写),它允许我们检查多个条件。如果第一个条件失败,它会检查第二个条件,如果第二个条件也失败,则执行 else 代码块。

(3)for 循环

1. 基本的 for 循环

在 Bash 中,最基本的 for 循环可以遍历一系列的值。

for 变量 in {list}
do 
  操作语句(可以多条)
done

        for循环执行次数和 list列表中常数或字符串的个数相同,先将in后面list列表的第一个常数或字符串赋值给变量,然后执行循环体;接着将list列表第二个赋值给变量,再次执行循环体。这个过程持续到list列表执行完,然后执行done后的操作命令。

#!/bin/bash

# 遍历列表中的每个元素
for fruit in apple banana cherry
do
  echo "I like $fruit"
done

        在这个例子中,for 循环遍历了列表 apple banana cherry 中的每个元素,并在每次迭代中将当前的元素赋值给变量 fruit,然后执行 echo 命令。

结果如下:

2. 使用通配符

for 循环也可以使用通配符来遍历文件。

#!/bin/bash

# 遍历当前目录下所有的 .txt 文件
for file in *.txt
do
  echo "Processing $file"
done

这个例子中,for 循环会遍历当前目录下所有扩展名为 .txt 的文件。

结果如下:

3. 使用序列

你可以使用 {start..end} 语法生成一个序列,并使用 for 循环遍历它。

#!/bin/bash

# 使用序列从 1 遍历到 5
for i in {1..5}
do
  echo "Number: $i"
done

这个例子中,for 循环会打印数字 1 到 5。

结果如下:

如果想遍历1-5内的所有奇数,只需将{1..5}改成{1..5..2}

#!/bin/bash

# 使用序列从 1 遍历到 5
for i in {1..5..2}
do
  echo "Number: $i"
done

结果如下: 

4. 使用 seq 命令

seq 命令可以生成一个数字序列,常与 for 循环结合使用。

#!/bin/bash

# 使用 seq 命令从 1 到 5,步长为 1
for i in $(seq 1 5)
do
  echo "Count: $i"
done

这个例子中,seq 1 5 生成一个从 1 到 5 的序列,for 循环遍历这个序列。

结果如下:

5. C 风格的 for 循环

Bash 也支持类似于 C 语言的 for 循环语法。

#!/bin/bash

# C 风格的 for 循环
for (( i=0; i<5; i++ ))
do
  echo "Index: $i"
done

        这个例子中,for 循环使用类似于 C 语言的控制变量 i,初始化为 0,并在每次迭代后递增,直到 i 小于 5 为止。

结果如下:


(4)while 循环

while 循环是一种控制结构,它重复执行一组命令,直到给定的条件不再为真。

1. 基本的 while 循环

这是一个基本的 while 循环,它将一直执行,直到条件变为假。

while 条件测试表达式
do 
操作语句(可以多条)
done
#!/bin/bash

# 初始化计数器
count=1

# while 循环,直到 count 大于 5
while [ $count -le 5 ]
do
  echo "Count: $count"
  # 增加计数器的值
  ((count++))
done

        在这个例子中,while 循环会一直执行,直到变量 count 的值大于 5。每次循环,它都会打印当前的 count 值,并将其递增。

结果如下:

2. 读取文件行

while 循环常用于读取文件中的每一行。

#!/bin/bash

# 读取文件中的每一行
while read line
do
  echo "$line"
done < "filename.txt"

        这个例子中,while 循环使用 read 命令从文件 “filename.txt” 中读取每一行,并打印它。循环会继续,直到文件中没有更多的行可以读取。

  • 例如我有一个study.txt 文件,所以我执行下面的内容

#!/bin/bash

# 读取文件中的每一行
while read line
do
  echo "$line"
done < "study.txt"

结果如下: 

3. 无限循环

如果你不提供退出条件,while 循环将变成一个无限循环。

#!/bin/bash

# 无限循环
while true
do
  echo "Looping forever..."
  sleep 1  # 等待 1 秒
done

        这个例子中,while 循环会无限地执行,每次循环打印消息并暂停一秒钟。要停止这个循环,你需要手动中断脚本(例如,按 Ctrl+C)。

结果如下:

4. 使用控制变量

在 while 循环中,你可以使用一个控制变量来决定何时退出循环。

#!/bin/bash

# 控制变量
number=1

# while 循环,直到 number 大于 5
while [ $number -le 5 ]
do
  echo "Number: $number"
  ((number++))
  # 如果 number 等于 4,则退出循环
  if [ $number -eq 4 ]; then
    break
  fi
done

在这个例子中,while 循环在 number 达到 4 时通过 break 命令提前退出。

结果如下:


8.函数

        在 Bash 脚本中,函数是一段可重用的代码块,它可以接受参数,执行一系列命令,并可能返回一个值。

1. 定义和调用一个简单的函数

下面是一个定义和调用简单函数的例子:

#!/bin/bash

# 定义函数 greet
greet() {
  echo "Hello, $1!"
}

# 调用函数 greet 并传递参数 "World"
greet "World"

 或者

#!/bin/bash

# 定义函数 greet
function greet() {
  echo "Hello, $1!"
}

# 调用函数 greet 并传递参数 "World"
greet "World"

        在这个例子中,greet 是一个接受一个参数的函数。当你调用 greet "World" 时,它会在屏幕上打印 “Hello, World!”。

结果如下:

如果你想要在终端上输入你想要的内容可以加上read 命令

#!/bin/bash

# 定义函数 greet
function greet() {
  echo "Hello,$context !"
}

# 调用函数 greet 并传递参数 "World"
read -p "请输入内容:" context
greet $context

结果如下:

 

2. 使用局部变量

        默认情况下,Bash 函数中的变量是全局的。如果你想要在函数内部使用局部变量,可以使用 local 关键字。

#!/bin/bash

# 定义函数 greet_with_local
greet_with_local() {
  local name=$1
  echo "Hello, $name!"
}

# 调用函数 greet_with_local
greet_with_local "Alice"

在这个例子中,name 是一个局部变量,它只在 greet_with_local 函数内部有效。

3. 函数返回值

Bash 函数可以通过 return 语句返回一个整数,或者通过 echo 来返回字符串。

#!/bin/bash

# 定义函数 add,返回两个数的和
add() {
  local a=$1
  local b=$2
  local sum=$((a + b))
  echo $sum
  # 或者使用 return 语句返回整数结果
  # return $sum
}

# 调用函数 add 并获取返回值
result=$(add 5 3)
echo "The result is $result"

        在这个例子中,add 函数接受两个参数,计算它们的和,并通过 echo 返回结果。调用函数时,可以使用 $() 来捕获函数的输出。

4. 函数中使用位置参数

Bash 函数可以像脚本一样使用位置参数 $1$2$3 等。

#!/bin/bash

# 定义函数 print_params
print_params() {
  echo "Parameter 1: $1"
  echo "Parameter 2: $2"
  echo "All parameters: $*"
}

# 调用函数 print_params 并传递参数
print_params "First" "Second" "Third"

在这个例子中,print_params 函数打印了传递给它的每个参数,以及所有参数的列表。


9.数组

        在 Bash 中,数组是一组数据的集合,可以存储一个或多个元素。数组元素可以是任何数据类型,但通常使用字符串和整数。

(1)数组的定义

在Shell脚本中,数组可以通过以下两种方式之一来定义:

1.显式定义:使用括号()和空格分隔的元素来定义数组。

# 定义一个包含三个元素的数组  
my_array=(element1 element2 element3)

2.隐式定义:通过赋值给数组的索引来定义数组。

# 逐个定义数组元素  
my_array[0]=element1  
my_array[1]=element2  
my_array[2]=element3

(2)访问数组元素

数组元素可以通过索引来访问,索引从0开始。

# 访问第一个元素  
echo ${my_array[0]}  # 输出: element1  
  
# 访问第二个元素  
echo ${my_array[1]}  # 输出: element2

(3)获取数组长度

可以使用特殊变量${#array_name[@]}${#array_name[*]}来获取数组的长度(即元素的个数)。

# 获取数组长度  
array_length=${#my_array[@]}  
echo $array_length  # 输出: 3

(4)遍历数组

可以使用for循环来遍历数组元素。

# 使用for循环遍历数组  
for element in "${my_array[@]}"; do  
    echo $element  
done

或者,使用数组的索引来遍历:

# 使用索引遍历数组  
for i in "${!my_array[@]}"; do  
    echo "Element at index $i: ${my_array[$i]}"  
done

注意事项

  • Shell脚本中的数组是一维的,不支持多维数组。
  • 数组索引是从0开始的整数。
  • 在访问数组元素时,建议使用双引号将变量名括起来(如${my_array[0]}),以避免在元素包含空格或特殊字符时出现问题。
  • 在某些Shell(如Dash,它是Debian和Ubuntu的/bin/sh的默认Shell)中,数组功能可能受到限制或不完全支持。因此,在编写依赖于数组功能的脚本时,最好指定使用Bash(或其他支持数组的Shell)。

http://www.kler.cn/news/357116.html

相关文章:

  • manjaro kde 磁盘扩容
  • Leecode热题100-101.对称二叉树
  • 等保测评中的安全培训与意识提升
  • SQL Server 2019数据库“正常,已自动关闭”
  • 【Orange Pi 5 Linux 5.x 内核编程】-驱动程序参数
  • 删除node_modules文件夹
  • 《YOLO1》论文精读:第一次实现端到端的目标检测
  • MFC工控项目实例二十五多媒体定时计时器
  • Pollard‘s p-1算法
  • 工信部绿色工厂、绿色设计产品、绿色供应链企业、绿色园区名单(2017-2022年)
  • ORACLE 的SCHEDULER创建JOB
  • 【MogDB】MogDB5.2.0重磅发布第四篇-支持windows版gsql,兼容sqlplus/sqlldr语法
  • 电影评论网站:Spring Boot技术栈应用
  • 压缩SQL Server 2014 数据库日志文件
  • OpenHarmony中EAP-PEAP认证支持 GTC方式
  • 【leetcode|哈希表、动态规划】最长连续序列、最大子数组和
  • 在合规的地方怎么用EACO地球链兑换交换价值?
  • Linux操作系统切换设置系统语言
  • C++学习笔记----9、发现继承的技巧(三)---- 尊重父类(2)
  • [环境配置]macOS上怎么查看vscode的commit id