【Linux命令行与Shell脚本编程】第十六章 Shell函数
Linux命令行与Shell脚本编程
第一章
文章目录
- Linux命令行与Shell脚本编程
- 六.函数
- 6.1.脚本函数基础
- 6.1.1.创建函数
- 6.1.2.使用函数
- 6.2.函数返回值
- 6.2.1.默认的退出状态码
- 6.2.2.使用return命令
- 6.2.3.使用函数输出
- 6.3.函数中使用变量
- 6.3.1.向函数传递参数
- 6.3.2.在函数中处理变量
- 全局变量
- 局部变量
- 6.4.数组变量和函数
- 6.4.1.向函数中传递数组
- 6.4.2.从函数返回数组
- 6.5.函数递归
- 6.6.创建库
- 6.7.在命令行中使用函数
- 6.7.1.命令行中创建函数
- 6.7.2.在.bashrc文件中定义函数
- 6.8.共享库函数
- 6.8.1.下载安装
六.函数
- 脚本函数基础
- 函数返回值
- 在函数中使用变量
- 数组变量和函数
- 函数递归
- 创建库
- 在命令行中使用函数
可以将shell脚本代码放入函数中封装起来,这样就能在脚本的任意位置多次使用.
6.1.脚本函数基础
函数是一个脚本代码块,可以并在脚本中的任何位置重用它。当需要在脚本中使用该代码块时,直接通过函数名调用.
6.1.1.创建函数
bash shell脚本中创建函数的语法有两种。
- 使用关键字function
function name {//函数的唯一名称。脚本中的函数名不能重复commands //组成函数的一个或多个bash shell命令。
}
- 近其他编程语言中定义函数的方式
name() {//函数名后的空括号表明正在定义的是一个函数
commands
}
6.1.2.使用函数
使用函数名调用函数
$ cat test1
#!/bin/bash
# using a function in a script
function func {echo "This is an example of a function"
}
count=1
while [ $count -le 5 ]
dofunccount=$[ $count + 1 ]
done
$ ./test1
This is an example of a function
This is an example of a function
This is an example of a function
This is an example of a function
This is an example of a function
- 函数定义不一定非要放在shell脚本的最开始部分,但必须定义在调用之后,在函数被定义之前调用,则会收到一条错误消息.
func: command not found
- 如果定义了同名函数,新定义就会覆盖函数原先的定义,而不会有任何错误消息.
6.2.函数返回值
bash shell把函数视为一个小型脚本,运行结束时会返回一个退出状态码.
有3种方法能为函数生成退出状态码。
6.2.1.默认的退出状态码
函数的退出状态码是函数中最后一个命令返回的退出状态码。函数执行结束后,可以使用标准变量 $? 来确定函数的退出状态码.
- 函数执行一结束就立刻读取返回值。用$?变量提取函数返回值之前执行了其他命令,函数的返回值会丢失。
#!/bin/bash
func1() {## 命令执行失败ls -l badfile
}
echo "testing the function: "
func1
echo "The exit status is: $?"
testing the function:
trying to display a non-existent file
ls: badfile: No such file or directory
The exit status is: 1
退出状态码是1,因为函数中的最后一个命令执行失败.使用函数的默认退出状态码是一种危险的做法.
ps: 函数最执行成功退出状态码为0.
6.2.2.使用return命令
bash shell会使用return命令以特定的退出状态码退出函数。return命令允许指定一个整数值作为函数的退出状态码.
$ cat test5
#!/bin/bash
# using the return command in a functionfunction dbl {read -p "Enter a value: " valueecho "doubling the value"return $[ $value * 2 ]
}dbl
echo "The new value is $?"
$
$ ./test5
Enter a value: 200
doubling the value
The new value is 1
$
大于255的任何数值都会产生错误的值.
6.2.3.使用函数输出
需要返回较大的整数值或字符串,可以将函数的’输出’保存到shell变量中.
result=$(function_name)
$ cat test5b
#!/bin/bash
# using the echo to return a value
function dbl {read -p "Enter a value: " valueecho $[ $value * 2 ]
}
result=$(dbl)
echo "The new value is $result"
$
$ ./test5b
Enter a value: 200
The new value is 400
$
$ ./test5b
Enter a value: 1000
The new value is 2000
$
函数会用echo语句来显示计算结果。脚本会获取dbl函数的输出,而不是查看退出状态码。
dbl函数实际上输出了两条消息。read命令输出了一条简短的消息来向用户询问输入值。
bash shell并不将其作为STDOUT输出的一部分,而是直接忽略。
如果用echo语句生成这条消息("Enter a value: ")来询问用户,消息就会与输出值一起被读入shell变量。
借助返回值方法,还可以返回浮点值和字符串.
6.3.函数中使用变量
在函数中使用变量时,需要注意变量的定义方式和处理方式。
6.3.1.向函数传递参数
bash shell会将函数当作脚本来对待。可以像普通脚本那样向函数传递参数.
函数名保存在$0变量中,函数参数依次保存在$1、 2 等变量中 . 可以用特殊变量 2等变量中.可以用特殊变量 2等变量中.可以用特殊变量#来确定传给函数的参数数量.
(处理用户输入章节)
脚本中调用函数时,必须将参数和函数名放在同一行.然后用位置变量来获取参数值。
func_name $value1 10
示例:
$ cat test6
#!/bin/bash
function addem {if [ $# -eq 0 ] || [ $# -gt 2 ]thenecho -1elif [ $# -eq 1 ]thenecho $[ $1 + $1 ]elseecho $[ $1 + $2 ]fi
}echo -n "Adding 10 and 15: "
value=$(addem 10 15)
echo $value
echo -n "Let's try adding just one number: "
value=$(addem 10)
echo $value
echo -n "Now try adding no numbers: "
value=$(addem)
echo $value
echo -n "Finally, try adding three numbers: "
value=$(addem 10 15 20)
echo $value
$
$ ./test6
Adding 10 and 15: 25
Let's try adding just one number: 20
Now try adding no numbers: -1
Finally, try adding three numbers: -1
函数使用位置变量访问函数参数,无法直接获取脚本的命令行参数。
$ cat badtest1
#!/bin/bash
# trying to access script parameters inside a functionfunction badfunc1 {echo $[ $1 * $2 ]
}if [ $# -eq 2 ]
thenvalue=$(badfunc1)echo "The result is $value"
elseecho "Usage: badtest1 a b"
fi
$
$ ./badtest1
Usage: badtest1 a b
$ ./badtest1 10 15
./badtest1: * : syntax error: operand expected (error token is "*")
The result is
$
尽管函数使用了$1变量和$2变量,但和脚本主体中的$1变量和$2变量不同。
要在函数中使用脚本的命令行参数,必须在调用函数时手动将其传入.
value=$(badfunc1 $1 $2)
在将$1和$2传给函数后就能跟其他变量一样供函数使用。
6.3.2.在函数中处理变量
变量的作用域是比较麻烦的.作用域是变量的有效区域.
函数有两种类型的变量:
- 全局变量
- 局部变量
全局变量
在shell脚本内任何地方都有效的变量。
在默认情况下,在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问.
$ cat test8
#!/bin/bash
function dbl {value=$[ $value * 2 ]
}
read -p "Enter a value: " value
dbl
echo "The new value is: $value"
$
$ ./test8
Enter a value: 450
The new value is: 900
$value变量在函数外定义并被赋值。如果变量在函数内被赋予了新值,那么在脚本中引用该变量时,新值仍可用。
局部变量
在任何在函数内部使用的变量都可以被声明为局部变量.local关键字保证了变量仅在该函数中有效。
- 在变量声明之前加上local关键字.
- 在变量赋值语句中使用local关键字.
local temp
local temp=$[ $value + 5 ]
如果函数之外有同名变量,两个变量的值互不干扰。
function func1 {local temp=$[ $value + 5 ]result=$[ $temp * 2 ]
}
6.4.数组变量和函数
在函数中使用数组变量.
6.4.1.向函数中传递数组
将数组变量当作单个参数传递不起作用.
数组变量作为函数参数进行传递,则函数只会提取数组变量的第一个元素。
$ cat badtest3
#!/bin/bash
function testit {echo "The parameters are: $@"thisarray=$1echo "The received array is ${thisarray[*]}"
}
myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
testit $myarray
$
$ ./badtest3
The original array is: 1 2 3 4 5
The parameters are: 1
The received array is 1
必须先将数组变量拆解成多个数组元素,然后将这些数组元素作为函数参数传递。最后在函数内部,将所有的参数重新组合成一个新的数组变量。
$ cat test11
#!/bin/bash
function addarray {local sum=0local newarraynewarray=(`echo "$@"`)for value in ${newarray[*]}dosum=$[ $sum + $value ]doneecho $sum
}
myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
arg1=$(echo ${myarray[*]})
result=$(addarray $arg1)
echo "The result is $result"
$
$ ./test11
The original array is: 1 2 3 4 5
The result is 15
6.4.2.从函数返回数组
函数向shell脚本返回数组变量先用echo语句按正确顺序输出数组的各个元素,脚本再将数组元素重组成一个新的数组变量.
$ cat test12
#!/bin/bash
function arraydblr {local origarraylocal newarraylocal elementslocal iorigarray=($(echo "$@"))newarray=($(echo "$@"))elements=$[ $# - 1 ]for (( i = 0; i <= $elements; i++ )){newarray[$i]=$[ ${origarray[$i]} * 2 ]}echo ${newarray[*]}
}
myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
arg1=$(echo ${myarray[*]})
result=($(arraydblr $arg1))
echo "The new array is: ${result[*]}"
$
$ ./test12
The original array is: 1 2 3 4 5
The new array is: 2 4 6 8 10
通过$arg1变量将数组元素作为参数传给arraydblr函数。
arraydblr函数将传入的参数重组成新的数组变量,生成数组变量的副本。对数据元素进行操作,并将结果存入函数中的数组变量副本。
6.5.函数递归
函数可以递归地调用.
递归函数通常有一个最终可以迭代到的基准值。
递归算法的经典例子是计算阶乘:
$ cat test13
#!/bin/bash
function factorial {if [ $1 -eq 1 ]thenecho 1elselocal temp=$[ $1 - 1 ]local result=$(factorial $temp)echo $[ $result * $1 ]fi
}
read -p "Enter value: " value
result=$(factorial $value)
echo "The factorial of $value is: $result"
$
$ ./test13
Enter value: 5
The factorial of 5 is: 120
6.6.创建库
使用函数可以为脚本省去一些重复性的输入工作.如果要在多个脚本中使用同一段代码,通过库解决.
bash shell允许创建函数库文件,然后在多个脚本中引用此库文件。
- 创建一个包含脚本中所需函数的公用库文件。
$ cat myfuncs function addem {echo $[ $1 + $2 ] } function multem {echo $[ $1 * $2 ] }
- 在需要用到这些函数的脚本文件中包含myfuncs库文件.
shell函数的作用域和环境变量一样,shell函数仅在定义它的shell会话内有效。
如果在shell命令行界面运行myfuncs脚本,那么shell会创建一个新的shell并在其中运行这个脚本。
这种情况下,函数会定义在新shell中,当运行另一个要用到这些函数的脚本时,它们是无法使用的。
如果尝试像普通脚本文件那样运行库文件,函数也不会出现在脚本中.
使用函数库的关键在于source命令。$ cat badtest4 #!/bin/bash # using a library file the wrong way ./myfuncs result=$(addem 10 15) echo "The result is $result" $ $ ./badtest4 ./badtest4: addem: command not found The result is
source命令不会创建新的shell,而是在当前shell的上下文中执行命令.
source命令称作点号操作符。在shell脚本中运行myfuncs库文件,只需添加:
假定myfuncs库文件和shell脚本位于同一目录。否则需要使用正确路径访问该文件。. ./myfuncs
$ cat test14 #!/bin/bash . ./myfuncs value1=10 value2=5 result1=$(addem $value1 $value2) echo "The result of adding them is: $result1" $ $ ./test14 The result of adding them is: 15
6.7.在命令行中使用函数
有时候,在命令行界面用函数执行一些十分复杂的操作.
6.7.1.命令行中创建函数
shell会解释用户输入的命令,可以在命令行中直接定义一个函数.
在命令行创建函数时要特别小心。如果给函数起了一个跟内建命令或另一个命令相同的名字,那么函数就会覆盖原来的命令。
- 单行方式
在命令行中定义函数时,必须在每个命令后面加个分号,用于界定命令的起止.$ function divem { echo $[ $1 / $2 ]; } $ divem 100 5 20
- 多行方式
定义时,bash shell会使用次提示符’>'来提示输入更多命令。使用这种方法,无须在每条命令的末尾放置分号,只需按下回车键.
输入函数尾部的花括号后完成函数的定义.$ function multem { > echo $[ $1 * $2 ] > } $ multem 2 5 10
在命令行中直接定义shell函数的一个明显缺点是,在退出shell时,函数也会消失。
在命令行创建函数时要特别小心。如果给函数起了一个跟内建命令或另一个命令相同的名字,函数就会覆盖原来的命令。
6.7.2.在.bashrc文件中定义函数
解决退出shell函数消失的问题.
将函数定义在每次新shell启动时都会重新读取该函数的地方。
.bashrc文件,不管是交互式shell还是从现有shell启动的新shell,bash shell在每次启动时都会在用户主目录中查找这个文件。
- 直接定义函数
直接在用户主目录的.bashrc文件中定义函数。将函数放在文件末尾.
函数会在下次启动新的bash shell时生效。随后就能在系统中的任意地方使用这个函数。$ cat .bashrc # .bashrc # Source global definitions if [ -r /etc/bashrc ]; then. /etc/bashrc fi function addem {echo $[ $1 + $2 ] } $
- 源引函数文件
只要是在shell脚本中,就可以用source命令(或别名即点号操作符)将库文件中的函数添加到.bashrc脚本中.确保库文件的路径名正确.$ cat .bashrc # .bashrc # Source global definitions if [ -r /etc/bashrc ]; then. /etc/bashrc fi . /home/rich/libraries/myfuncs $
shell会将定义好的函数传给子shell进程,这些函数就能够自动用于该shell会话中的任何子shell脚本.
用源引库文件,这些函数就可以在shell脚本中顺畅运行。
6.8.共享库函数
在开源世界中,共享代码是必不可少的,同样适用于shell脚本函数。可以下载各种shell脚本函数并将其用于自己的应用程序中。
下载、安装以及使用GNU shtool shell脚本函数库。shtool库提供了一些简单的shell脚本函数,可用于实现日常的shell功能,比如处理临时文件和目录、格式化输出显示等。
6.8.1.下载安装
- 将GNU shtool库下载并安装到你的系统中.
wget http://ftp.gnu.org/gnu/shtool/shtool-2.0.8.tar.gz
- 将文件复制到主目录中.
- 使用tar命令提取文件.
tar -zxvf shtool-2.0.8.tar.gz
- 进入到解压新创建的目录
- 构建库文件
使用标准的configure命令和make命令$ ./configure $ make
configure命令会检查构建shtool库文件所必需的软件。发现了所需的工具,会使用工具路径修改配置文件。
make命令负责构建shtool库文件。最终的shtool文件是一个完整的库软件包文件。
可以使用make命令测试库文件
$ make test
Running test suite:
echo...........ok
... ... 略
OK: passed: 19/19
测试模式会测试shtool库中所有的函数。如果全部通过了测试,就可以将库安装到Linux系统中的公用位置,这样你的所有脚本就都能使用这个库了。
以root用户使用make命令的install选项完成安装.
# make install
Password:
./shtool mkdir -f -p -m 755 /usr/local
... ...
./shtool install -c -m 644 sh.version /usr/local/share/shtool/sh.version
./shtool install -c -m 644 sh.path /usr/local/share/shtool/sh.path
# shtool -v
GNU shtool 2.0.8 (18-Jul-2008)
安装成功,可以使用了.
相关文章:

【Linux命令行与Shell脚本编程】第十六章 Shell函数
Linux命令行与Shell脚本编程 第一章 文章目录 Linux命令行与Shell脚本编程六.函数6.1.脚本函数基础6.1.1.创建函数6.1.2.使用函数 6.2.函数返回值6.2.1.默认的退出状态码6.2.2.使用return命令6.2.3.使用函数输出 6.3.函数中使用变量6.3.1.向函数传递参数6.3.2.在函数中处理变量…...

SpringCloud-Hystrix服务熔断与降级工作原理源码 | 京东物流技术团队
先附上Hystrix源码图 在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplateRibbon和Feign来调用。为了保证其高可用,单个服务通常会集群部署。…...
(一)react脚手架
1. react脚手架 react提供了一个用于创建react项目的脚手架库:create-react-app 项目的整体技术架构为:react webpack es6 eslint 使用脚手架开发的项目的特点:模块化、组件化、工程化 2. 创建项目并启动 # 第一步: 全局安…...

Typescript中的元组与数组的区别
Typescript中的元组与数组的区别 元组可以应用在经纬度这样明确固定长度和类型的场景下 //元组和数组类似,但是类型注解时会不一样//元组赋值的类型、位置、个数需要和定义的类型、位置、个数完全一致,不然会报错。 // 数组 某个位置的值可以是注解中的…...

SpringBoot的index首页的访问、自定义Favicon图标
目录 1. index首页1.1 index首页访问规则的源码1.2 index首页的访问 2. 自定义Favicon图标 1. index首页 1.1 index首页访问规则的源码 package org.springframework.boot.autoconfigure.web.servlet; ......省略部分......// SpringBoot给容器中放WebMvcConfigurationSuppor…...

【C++】C++文件操作-文本文件/二进制文件
0.前言 一、文本文件 1.写文件 代码 #include <iostream> using namespace std; #include <fstream> //头文件包含//************************************** //文本文件 写文件 void test01() {//1.包含文件 fstream//2.创建流对象ofstream ofs;//3.指导打开方式…...
java通过http网络url下载文件
Testpublic void test3() throws ParseException {String fileUrl "http://*****/123.pdf";String savePath "C:\\Users\\HHH\\Desktop\\文件\\123.pdf";try {URL url new URL(fileUrl);InputStream inputStream url.openStream();Path outputPath Pa…...

网络安全【黑客】自学
1.什么是网络安全? 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域,都有…...

PCA和自动编码器:每个人都能理解的算法
一、说明 本文的主要重点是提供主成分分析 (PCA) 和自动编码器数据转换技术的直观信息。我不打算深入研究支撑这些模型的数学理论,因为已经有大量的资源可用。 二、pca降维和自编码 2.1 pca和自编码的共同点 自动编码器通过组合数据最重要的特…...

C++——STL容器【priority_queue】模拟实现
本章代码:优先级队列模拟实现、priority_queue文档 文章目录 🐈1. priority_queue介绍🦄2. priority_queue模拟实现🐧2.1 构造函数🐧2.2 建堆向下调整向上调整 🐧2.3 仿函数🐧2.4 push & po…...

SpringBoot实现文件记录日志,日志文件自动归档和压缩
😊 作者: Eric 💖 主页: https://blog.csdn.net/weixin_47316183?typeblog 🎉 主题:SpringBoot实现文件记录日志,日志文件自动归档和压缩 ⏱️ 创作时间: 2023年08月06日 文章目…...

MySQL 窗口函数
聚合函数作为窗口函数 设聚合函数为op语法结构: op(字段名A) over(partition by 字段名B order by 字段名C rows between D1 and D2) 其中: partition by:按照某一字段将数据进行分组 order by:按照某一字段将数据进行排序&…...

0140 数据链路层2
目录 3.数据链路层 3.6局域网 3.7广域网 3.8数据链路层设备 部分习题 3.数据链路层 3.6局域网 3.7广域网 3.8数据链路层设备 部分习题 1.如果使用5类UTP来设计一个覆盖范围为200m的10BASE-T以太网,需要采用的设备是() A.放大器 …...
Python字典的应用场景
Python字典是一种无序、可变的数据类型,它由键值对组成。字典在Python中被广泛应用,以下是一些常见的应用场景: 数据存储和检索:字典可以用来存储和检索大量的数据,通过使用键来快速访问对应的值。例如,可以…...
关于外贸跟进客户过程中需要注意的地方
如果你感觉业务进展困难,多去看一些书,多去链接一些人,特别是优秀的人,多交流会让你思维更加开阔,笔记做好实践起来,就会有收获! 我记得汪老师说过:跟进客户,当你准备好…...

AI绘画:两组赛博咒语和ComfyUI使用方法
虽迟但到啊,上次说过要发,必然是要发滴! 本来我是可以直接发的,但是我又想着发关键词的同时,最好是讲解一下用法,这样更友好。所以就拖了一天! 下面先展示一下两套咒语的效果: 这套…...

Nacos源码 (2) 核心模块
返回目录 整体架构 服务管理:实现服务CRUD,域名CRUD,服务健康状态检查,服务权重管理等功能配置管理:实现配置管CRUD,版本管理,灰度管理,监听管理,推送轨迹,聚…...
MySQL之深入InnoDB存储引擎——Buffer Pool
文章目录 一、空闲链表的管理二、缓冲页的哈希处理三、Flush链表的管理四、LRU链表的管理五、脏页刷新六、多Buffer Pool实例 InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。在数据库系统中,由于CPU速度与磁盘速度之间的鸿沟&…...

网络安全(秋招)如何拿到offer?(含面试题)
以下为网络安全各个方向涉及的面试题,星数越多代表问题出现的几率越大,祝各位都能找到满意的工作。 注:本套面试题,已整理成pdf文档,但内容还在持续更新中,因为无论如何都不可能覆盖所有的面试问题…...
笙默考试管理系统-MyExamTest----classranking(2)
笙默考试管理系统-MyExamTest----classranking(2) 目录 笙默考试管理系统-MyExamTest----classranking(2) 一、 笙默考试管理系统-MyExamTest----classranking 二、 笙默考试管理系统-MyExamTest----classranking 三、 笙…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...