python中的fire和Linux shell中的参数传递

一、fire

安装

要使用 Python Fire 库,首先需要安装它。以下是安装步骤:

使用 pip 安装

可以通过 pip 直接安装 Python Fire:

pip install fire

特性

  1. 自动生成命令行界面:将任何 Python 对象(函数、类、模块、字典等)自动转换为命令行界面。

  2. 简洁性:只需一行代码即可生成命令行界面,大大减少了开发时间和代码复杂度。

  3. 灵活性:支持多种数据类型和参数,能够处理复杂的命令行需求。

  4. 易用性:与 Python 标准库无缝集成,易于上手和使用。

基本功能

将函数转换为命令行工具

可以将一个简单的函数转换为命令行工具:

import firedef greet(name):return f'Hello, {name}!'if __name__ == '__main__':fire.Fire(greet)

在命令行中运行:

python greet.py John

输出:

Hello, John!

将类转换为命令行工具

可以将一个类转换为命令行工具:

import fireclass Calculator:def add(self, a, b):return a + bdef multiply(self, a, b):return a * bif __name__ == '__main__':fire.Fire(Calculator)

在命令行中运行:

python calculator.py add 2 3
python calculator.py multiply 2 3

输出:

5
6

将字典转换为命令行工具

可以将一个字典转换为命令行工具:

import fireoperations = {'add': lambda a, b: a + b,'multiply': lambda a, b: a * b,
}if __name__ == '__main__':fire.Fire(operations)

在命令行中运行:

python operations.py add 2 3
python operations.py multiply 2 3

输出:

5
6

高级功能

处理复杂的数据类型

Python Fire 支持处理复杂的数据类型,如列表、字典等:


import firedef process_list(items):return [item.upper() for item in items]if __name__ == '__main__':fire.Fire(process_list)

在命令行中运行:

python process_list.py --items a b c

输出:

['A', 'B', 'C']

使用嵌套命令

可以使用嵌套命令来处理复杂的命令行操作:

import fireclass FileManager:def read(self, filename):with open(filename, 'r') as file:return file.read()def write(self, filename, content):with open(filename, 'w') as file:file.write(content)return f'{filename} has been written.'if __name__ == '__main__':fire.Fire(FileManager)

在命令行中运行:

python filemanager.py read test.txt
python filemanager.py write test.txt "Hello, World!"

自定义命令行参数

可以自定义命令行参数,提供更多控制和灵活性:

import firedef greet(name, greeting='Hello'):return f'{greeting}, {name}!'if __name__ == '__main__':fire.Fire(greet)

在命令行中运行:

python greet.py John --greeting Hi

输出:

Hi, John!

实际应用场景

数据处理脚本

在数据处理脚本中,通过 Python Fire 将函数或类转换为命令行工具,简化数据处理流程。

import fire
import pandas as pddef process_data(filename):df = pd.read_csv(filename)df['processed'] = df['data'] * 2df.to_csv('processed_' + filename, index=False)return 'Data processed.'if __name__ == '__main__':fire.Fire(process_data)

在命令行中运行:

python process_data.py data.csv

自动化运维脚本

在自动化运维脚本中,通过 Python Fire 将类转换为命令行工具,简化服务器管理和运维操作。

import fire
import osclass ServerManager:def start(self, service):os.system(f'systemctl start {service}')return f'{service} started.'def stop(self, service):os.system(f'systemctl stop {service}')return f'{service} stopped.'if __name__ == '__main__':fire.Fire(ServerManager)

在命令行中运行:

python server_manager.py start nginx
python server_manager.py stop nginx

开发测试工具

在开发测试工具中,通过 Python Fire 将函数或类转换为命令行工具,简化测试流程。

import fire
import requestsdef test_api(endpoint):response = requests.get(endpoint)return response.json()if __name__ == '__main__':fire.Fire(test_api)

在命令行中运行:

python test_api.py https://api.example.com/data

二、Linux shell 中传递参数

来自命令行的参数传递

有时候 shell 脚本需要与用户进行交互,传递参数以供脚本读取,这时候就需要了解参数传递的过程。

传递参数的语法:./int.sh $HOME/LearningPerl/* 10

以上向脚本int.sh传递了两个参数,参数之间及参数和脚本之间用空格分开。参数之间的前后顺序也有规定的,这些称为位置参数,之所以说参数之间的顺序有规定,使因为其存入特殊变量不同,也就导致后续应用参数时的不同。

存入位置参数的特殊变量分别是:$1是第一个参数,$2是第二个参数,...,直到第九个参数$9,而$0是程序名,也就是脚本名。

因为参数之间是空格间隔的,所以当参数含有空格时,需要引号(单引号或双引号均可)将其圈起来。

#!/bin/bash
echo "I'm learning $1!"
./int.sh 'Linux shell'
# I'm learning Linux shell!

当传入的参数超过 ≥10 个时,这时就会有引用上的歧义,这个后面遇到再说何为歧义,这时候需要用花括号${}将 10 括起来,让 shell 知道你要引用第 10 个参数。

例如:

#!/bin/bash
echo "The tenth parameter is ${10}"
./int.sh 1 2 3 4 5 6 7 8 9 'Linux shell'
# The tenth parameter is Linux shell!

获取脚本名

虽然$0可以获取脚本名,但是有两个问题,一是命令会出现在$0中,比如脚本int.sh,在$0却是./int.sh,多了./,这不是我们想要的;还有就是,当指定脚本的路径时,$0也会完整保存路径和脚本名。

比如:bash /home/yan/LearningPerl/int.sh$0保存/home/yan/LearningPerl/int.sh,而不是int.sh,很多时候,我们只需要int.sh就行了,而不想要.//home/yan/LearningPerl/这些附属的字符。

幸运的是,有个basename命令可以很轻松的去除这些附属字符,只留下脚本名

#!/bin/bash
echo "The basename is $(basename $0)!"

这样,无论是./int.sh还是bash /home/yan/LearningPerl/int.sh就只留下int.sh了,这样,在调用脚本的时候就非常方便了。

测试参数

有时候,脚本设定要求提供参数,而实际中未提供时,会发生语法错误而导致程序崩溃,为了避免这种情况,就需要判断/测试是否提供了相应的参数给脚本使用。

-n用于测试参数。

#!/bin/bash
if test -n "$1"; thenfor line in $( cat $1)doecho $line | grep -Eo '\(\w+\)'done
elseecho "Please provide your file to iterate!"
fi

统计参数的个数

特殊变量$#储存有命令行提供的参数的个数。获取最后一个命令行参数,需要特别的写法${!#}

#!/bin/bash
params=$#
echo The number of parameters is $params
echo The last parameter is ${!#}
./int.sh a b c

输出:


The number of parameters is 3
The last parameter is c

在这里,可以清楚的看到$#!#的区别。获取第 10 命令行参数时,需要用花括号圈起来,如:${10}

还有一种特殊情况,就是没有参数传入时,$#为 0 可以理解,但是${!#}会返回脚本名。

./int.sh

输出:

The number of parameters is 0
The last parameter is ./int.sh
bash /home/yan/LearningPerl/int.sh

输出:

The number of parameters is 0
The last parameter is /home/yan/LearningPerl/int.sh

遍历命令行所有参数

bash shell 里面有两个特殊变量,储存命令行的所有参数,但是这两个特殊变量又稍有不同。

./int.sh fred dino barney

$*

这个变量会将所有命令行参数当成一个整体对待,这个整体有所有的命令行参数。

#!/bin/bash
for param in "$*"
doecho "\$* parameter is $param"
done
# $* parameter is fred dino barney

$@

这个变量会将每一个的命令行参数当成一个个独立的单词,这样可以用 for 循环遍历所有的参数。

#!/bin/bash
for param in "$@"
doecho "\$* parameter is $param"
done
# $* parameter is fred
# $* parameter is dino
# $* parameter is barney

有个好的方法记住这一特性,那就是在Perl里面@表示数组,自然而然地就会想到能迭代了。

shift 移动参数

shift的功能是将左边第一个参数弹出,而后参数顺移补上。先来看一个简单的例子了解其工作原理:

./int.sh fred dino barney
#!/bin/bash
echo "$*"
shift
echo "$*"
# fred dino barney
# dino barney

第一个echo打印了所有的参数,而第二个echo删除了最左边的 fred,这就是shift的工作原理。原先$1是 fred,shift之后的$1顺移变成了 dino,所以在使用 shift 后要牢记参数位置发生的变化。

shift命令默认删除最左边的第一个参数(也就是shift 1是默认的),也可以指定数字来删几个位置的参数。

#!/bin/bash
echo "$*"
shift 2
echo "$*"
echo $1
# fred dino barney
# barney
# barney

shift 2表示删除了最左边的两个参数,现在只剩最后一个参数了,相应的,$1也变成了 barney。

命令行选项

之前一直把命令行参数和选项搞混了,现在再来重新确定一下命令行参数和选项的区别。

为了区分选项和参数,Linux 特意将选项设置为单破折线后面跟一个字母,而参数则不需要单破折线。

例如:./int.sh -a sample,在这里,-a是选项,sample是参数。

要想写出一个鲁棒性强的脚本,必须兼顾各种情况,而选项恰恰是提供这种鲁棒性的工具。

  1. 首先,需要区分是选项还是参数?

    这部分内容的实现,需要一个判断语句case,配合之前的shift命令,结合while循环进行判断。

#!/bin/bash
while test -n "$1"
docase "$1" in-a) echo "-a is a option" ;;-b) echo "-b is a option" ;;-c) echo "-c is a option" ;;*) echo "$1 is not a option" ;;esacshift
done

这样就能识别出特定的选项了。

  1. 区分选项和参数

    之所以要区分选项和参数,原因是没有必要遍历所有的命令行选项和参数,你把所有的命令行选项和参数遍历了一遍,shift命令就将所有的输入删除殆尽了,你要想调用参数已经被删除掉了,这种为了判断选项而遍历所有的输入不值当。换句话说,对于选项而言,我只需要遍历和判断选项,剩下的都当作参数处理。

    来看一个具体的例子就知道上面说的啥意思了:

#!/bin/bash
while test -n "$1"
docase "$1" in-a) echo "-a is a option" ;;-b) echo "-b is a option" ;;*) echo "$1 is not a option" ;;esacshift
donefor var in "$@"
doecho "opening file $var"
done

./int.sh -a -b -c fred dino barney输出:

-a is a option
-b is a option
-c is not a option
fred is not a option
dino is not a option
barney is not a option

可以看到,后面的 fred、dino 和 barney 文件并没有被输出。这就是没有区别选项和参数的局限所在了。参数都被删除完了,后面想迭代已经没有了。

在 Linux 中,通常使用双破折线--来界定选项和参数。这样分开的好处是,可以及时打破循环,只对选项进行迭代,终止迭代参数,这样在后面的命令在就可以继续使用参数了,来看例子:

#!/bin/bash
while test -n "$1"
docase "$1" in-a) echo "-a is a option" ;;-b) echo "-b is a option" ;;--) shiftbreak ;;*) echo "$1 is not a option" ;;esacshift
donefor var in "$@"
doecho "opening file $var"
done

./int.sh -a -b -c -- fred dino barney输出:

-a is a option
-b is a option
-c is not a option
opening file fred
opening file dino
opening file barney

这个就是选项和参数分开的妙处。

  1. 处理带值的选项

    这要是选项和参数完全分开没啥问题,但是现实是有的选项带有值,这时候就需要针对带值的选项进行特殊处理。

#!/bin/bash
while test -n "$1"
docase "$1" in-a) echo "-a is a option" ;;-b) value="$2"echo "-b is a option with a value '$value'" ;;--) shiftbreak ;;*) echo "$1 is not a option" ;;esacshift
donefor param in "$@"
doecho "opening a file $param"
done

./int.sh -a -b today -c -- fred dino barney,现在-b选项带有值today,来看输出结果:

-a is a option
-b is a option with a value 'today'
today is not a option
-c is not a option
opening a file fred
opening a file dino
opening a file barney

有点小问题,就是today值不应该被判断为选项而打印出来,这时需要将其shift删除掉。

#!/bin/bash
while test -n "$1"
docase "$1" in-a) echo "-a is a option" ;;-b) value="$2"echo "-b is a option with a value '$value'"shift ;;--) shiftbreak ;;*) echo "$1 is not a option" ;;esacshift
donefor param in "$@"
doecho "opening a file $param"
done

./int.sh -a -b today -c -- fred dino barney,再来看输出结果:


-a is a option
-b is a option with a value 'today'
-c is not a option
opening a file fred
opening a file dino
opening a file barney

这次就完美了,非常符合预期结果,既个性化处理了带值的选项,同时也能对参数进行处理。

基于shift命令的特性,每次读取后就将其删除,所以,只要带值的选项格式是:选项+值(例如本例中-b today),无论无何变换位置(如:-b today -a -c-c -a -b today等),都不影响处理带值的选项,但是不能把选项及其值分开(如本例:``-b -a today -c`这样的不行)。

需要强调的是:不管按什么顺序位置放置选项,都必须将带值的选项当作一个整体放置,程序都能正常运行。

./int.sh -b today -c -a -- fred dino barney

-b is a option with a value 'today'
-c is not a option
-a is a option
opening a file fred
opening a file dino
opening a file barney
  1. 处理合并选项

    现实中有许多人喜欢将选项合并写,这样可以省去键入的次数,但是以上所学还不足以实现选项的合并处理,这时需要使用getopt命令来帮助实现这一需求。

    getopt命令的用法:getopt optstring parameters

    来看具体例子(选项不带值):

getopt abc -a -b -c fred dino barney
# -a -b -c -- fred dino barbey

选项带值:

getopt a:bc -a value1 -b -c fred dino barney
# -a value1 -b -c -- fred dino barbey
getopt a:b:c -a value1 -b value2 -c fred dino barney
# -a value1 -b value2 -c -- fred dino barbey
getopt a:b::c -a value1 -b value2 value3 -c fred dino barney
# -a value1 -b  -c -- value2 value3 fred dino barbey
getopt a:b::c -a value1 -b value2 -c fred dino barbey
# -a value1 -b  -c -- value2 fred dino barbey
getopt a:b:c -a value1 -b value2 value3 -c fred dino barbey
# -a value1 -b value2 -c -- value3 fred dino barbey
getopt a:bc -bc -a value1 fred dino barbey
# -b -c -a value1 -- fred dino barbey
getopt a:b:c -bc -a value1 fred dino barbey
# -b c -a value1 -- fred dino barbey

从以上例子可以看出,optstring先是定义了所要的选项,这些例子中是 a、b 和 c,如果某个选项带有值,则在其后面加上冒号:,选项不能带有多个值,也不能写两个冒号及以上表示多个值,只能由一个冒号表示一个值,否则结果将不符合预期。所以,安全起见,就一个冒号一个值吧。

再来说说getopt命令的运行原理,首先,我们将getopt命令分为三个部分。

getopt a:bc -a value1 -bc fred dino barney
|----| |--| |------------------------------|⬇      ⬇                 ⬇
getopt optstring       parameters

当其运行时,getopt命令会检查parameters部分,并基于提供的optstring部分进行配对解析(顺序不影响其配对解析),当有合并的选项时(如这里的-bc),它会自动将其分成单独的两个选项,并用双破折线将选项和参数分开。

optstring部分有选项,而parameters部分没有时,会显示错误信息:

getopt a:bc -a value1 -bcd fred dino barney
# getopt: invalid option -- 'd'
# -a value1 -b -c -- fred dino barney

getopt命令的-q选项可以忽略这条消息,并同时给选项值和参数加上单引号:

getopt -q a:bc -a value1 -bcd fred dino barney
# -a 'value1' -b -c -- 'fred' 'dino' 'barney'

现在,就可以在脚本中实现选项的合并了。


#!/bin/bash
set -- $(getopt -q ab:c "$@")
while test -n "$1"
docase "$1" in-a) echo "-a is a option" ;;-b) value="$2"echo "-b is a option with a value '$value'"shift ;;-c) echo "-c is a option" ;;--) shiftbreak ;;*) echo "$1 is not a option" ;;esacshift
donefor param in "$@"
doecho "opening a file $param"
done

./int.sh -ac -b value fred dino


-a is a option
-c is a option
-b is a option with a value ''value''
opening a file 'fred'
opening a file 'dino'

这样,即使合并选项,也能正常处理选项和参数,并且能够做到选项和参数分开各自处理,已经接近完美了,但是还是差一点点。就是它在处理带空格和引号的参数时有问题。

./int.sh -ac "fred dino" barney

-a is a option
-c is a option
opening a file 'fred
opening a file dino'
opening a file 'barney'

可以看出,并不能正确解析参数。要想解决这一问题,还得引入更加高级的getopts 命令

  1. 更高级的 getopts 命令

    getopts optstring variable

    去掉错误消息,需要在optstring前加冒号:,如getopts :abc

    那么,variable保存的是什么呢?来看一个例子就懂了

#!/bin/bash
while getopts :abc var
doecho "$var"
done

./int.sh -abcd输出:

a
b
c
?

由此可见,variable保存的是在 while 循环中每次迭代optstring的单个选项,如果optstring中没有,就以问号?表示。

此外,getopts命令有两个特殊变量:

  • OPTARG 变量

当选项带有值时,OPTARG 变量就保存这个选项的值。

./int.sh -a -b fred -c

while getopts :ab:c var
doecho "$var"echo "-b option have a value $OPTARG"
done

输出:

a
-b option have a value
b
-b option have a value fred
c
-b option have a value

OPTIND 变量

OPTIND 变量保存了 getopts 正在处理的参数位置。如果在循环体内,则 OPTARG 变量会随着循环迭代而增加,如果是在循环体外,则保存有最后一次处理选项的位置信息。选项的值也会被计入其中。

#!/bin/bashwhile getopts :ab:c var
doecho "$var"echo "-b option have a value $OPTARG"
done
echo $OPTIND

输出:

a
-b option have a value
b
-b option have a value fred
c
-b option have a value
5

OPTIND 变量在循环体外,所以其保存了最后一次的选项位置,选项的值也被计入其中,而且,OPTIND 变量的值是位置上加 1,所以就成了 5,当我们需要 shift 选项时,则应在其基础上减 1 才符合实际。

另外需要注意的是,当合并键入选项时,会将那些合并的选项当成一个整体,然后在 OPTIND 变量中也相应的减少一,具体来看例子:

./int.sh -ab fred -c

a
-b option have a value
b
-b option have a value fred
c
-b option have a value
4

可以看到,尽管合并了选项,还是能正确解析出各个选项及其值,但是 OPTIND 变量变成 4 了,不是原来的 5 了。这么做也合理,你耐心看到后面就懂了。

getopts 命令在写法上也和 getopt 命令有所不同。

#!/bin/bashwhile getopts :ab:c var
docase "$var" ina) echo "Found the -a option" ;;b) echo "Found the -b option, with a value $OPTARG" ;;c) echo "Found the -c option" ;;*) echo "Unknown option: $var" ;;esac
done
echo $OPTIND
shift $[ $OPTIND - 1 ]
echo
for param in "$@"
doecho "Parameter: $param"
done

./int.sh -ab today -c dino barney peter

输出:

Found the -a option
Found the -b option, with a value today
Found the -c option
4Parameter: dino
Parameter: barney
Parameter: peter

./int.sh -a -b today -c dino barney peter


Found the -a option
Found the -b option, with value today
Found the -c option
5Parameter: dino
Parameter: barney
Parameter: peter

case语句中没有了破折线,并且直接在 while 循环语言的判断式中调用 getopts 命令对选项参数列表进行循环。

正如上面所说的,OPTIND 变量不论是合并的选项,还是分开键入的选项,都能够很好的解析选项和参数,结合 shift 命令,如果是合并的选项,就将其一块计入 OPTIND 变量中,shift 命令也能将其一并删除,选项解析还是以 case 进行判断,真可谓妙啊。

getopts 命令还可以正确处理带空格和引号的参数,这就是 getopts 命令比较高级的地方。

#!/bin/bash
while getopts :ab:c opt
docase "opt" ina) echo "Input -a option, processing..." ;;b) echo "Input -b option with a value $OPTARG, processing..." ;;c) echo "Input -c option, processing..." ;;*) echo "Sorry, error input.."esacdone
echo
shift $[ $OPTIND - 1 ]
for param in "$@"
doecho "Proccessing the parameter $param"
done

./int.sh -a -b today -c "dino barney" fred

Input -a option, processing...
Input -b option with a value today, processing...
Input -c option, processing...Proccessing the parameter dino barney
Proccessing the parameter fred

嗯,带双引号和空格的选项都能正常解析了,符合预期。

./int.sh -acb today "dino barney" fred./int.sh -ab today -c "dino barney" fred等等都能正常解析,但是一定要把 b 选项和 today 的顺序放一起,b 选项和 today 中间不能有别的值,如./int.sh -abc today "dino barney" fred这样就不能正常解析。

选项标准化

说人话就是,你自己创建 shell 脚本时,有权力去定义属于自己的脚本,选项可以按照自己的想法去定义,但是这样别人的学习成本就高了,将选项标准化的意思是将你的 shell 脚本写得更通俗普遍,而有些约定俗成的选项就不要去更改了,这样别人用起来也减少了学习成本,让你的脚本更容易被大众所接受,这就是选项标准化的实质。

已经约定俗成的选项代表的意义如下(部分例举):

  • -a 显示所有对象

  • -c 生成一个计数

  • -d 指定一个目录

  • -f 指定一个文件

  • -i 忽略文本大小写

  • -y 对所有问题回答 yes

获得输入(包括用户和文件的输入)

read命令接受来自标准键盘或文件的输入。

  • read命令读取文件时,需要借助cat命令和管道符,结合while循环读取。别忘了,当退出码为零时while循环继续,非零退出码时while终止。

#!/bin/bash
cat sample | while read line
doecho "$line"
done
  • read读取标准键盘输入。

#!/bin/bash
echo -n "Please enter your name: "
read name
echo "Hello, $name!"
#!/bin/bash
read -p "Please enter your name: " name
echo "Hello, $name!"

以上两个例子实现的效果一样,只是方式不同。

#!/bin/bash
read -p "Please enter your name and age: " name age
echo "Hi, $name, you are $age years old."

read命令会将输入分配给变量,如果输入与变量的数目一致,则变量得到对应位置的输入,如果变量的数量不够,剩下的输入数据就全部分配给最后的一个变量。

#!/bin/bash
read -p "Please enter your files: " fred dino barney
echo "here is the files your input: $fred $dino $barney "
Please enter your files: fred dino barney peter
here is the files your input: fred dino barney peter

Linux shell中还有一个特殊的变量,REPLY变量负责接收read命令输入的数据。前提是将设定的变量删除,否则$REPLY内空无一物。

#!/bin/bash
read -p "Please enter your files: "
for file in $REPLY
doecho "Processing file: $file"
done

等待超时

read命令-t选项来指定输入的时间,如果超过,规定时间,则终止输入并给予提示。

#!/bin/bash
if read -t 10 -p "Please enter your telephone whithin 10 seconds: ";
thenechoecho "Your telephone number $REPLY has been saved."
elseechoecho "Time out!"
fi

隐藏方式读取

-s选项可以避免将数据出现在显示器中,在输入密码时尤为合适。

#!/bin/bash
read -s  -p "Enter your password: " pass
if test $pass -eq '1234'; thenechoecho "your password is correct!"
elseechoecho "Sorry, It doesn't work!"
fi

现在,可以自己写 shell 脚本或 perl 脚本或 r 脚本,定义自己的选项和参数,创建一个鲁棒性强的脚本啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/49531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nodejs编译报错 集合

目录 一、使用命令编译typescript时报错,报错文件tsconfig.json 二、npm start运行后报错,could not find module 一、使用命令编译typescript时报错,报错文件tsconfig.json npx tsc 报错: Specified include paths were [&…

秋招突击——7/24——知识补充——JVM类加载机制

文章目录 引言类加载机制知识点复习类的生命周期1、加载2、连接——验证3、连接——准备4、连接——解析5、初始化 类加载器和类加载机制类加载器类加载机制——双亲委派模型 面试题整理1、类加载是什么2、类加载的过程是什么3、有哪些类加载器?4、双亲委派模型是什…

Redis一致性与分布式锁

Redis一致性 何为redis一致性 即在项目中,redis缓存中的数据要与数据库当中的数据保持一致。 那么这里,就会有小伙伴要问了,redis缓存中的数据不就是从数据库当中查询出来的吗?怎么会不一致呢? 笔者在这里解答一下…

Unite 上海 强势回归

​​​ 他回归了 Unite 大会是一年一度的 Unity 全球开发者盛会。今年,Unite 将于 7 月盛夏点亮上海外滩。此次盛会,我们将以“团结”为核心,凝聚全球 3000 多位 Unity 社区精英的力量,共同开启 Unity 技术的新纪元。 在这里&am…

UE学习笔记--干货满满!FString 的 Equals 和 == 源码深度探析

目录 前言FString 的 operatorESearchCaseStricmpBothAsciiLowerAsciiStricmp 结论Stricmp 代码验证整理思路 前言 最近大概写了如下代码 TArray<FString> TestArray; FString Z1 "Z1", z1 "z1"; TestArray.Emplace(Z1);if(TestArray.Contains(z…

代码随想录第十七天|动态规划(1)

目录 LeetCode 509. 斐波那契数列 LeetCode 70. 爬楼梯 LeetCode 746. 使用最小花费爬楼梯 LeetCode 62. 不同路径 LeetCode 63. 不同路径 II 总结 动态规划在算法课上学习过&#xff0c;看过了之后有一些熟悉感。&#xff08;虽然贪心算法也学过&#xff0c;但是不如动态…

样式迁移及代码

一、定义 1、使用卷积神经网络&#xff0c;自动将一个图像中的风格应用在另一图像之上&#xff0c;即风格迁移&#xff1b;两张输入图像&#xff1a;一张是内容图像&#xff0c;另一张是风格图像。 2、训练一些样本使得样本在一些cnn的特征上跟样式图片很相近&#xff0c;在一…

Java字符串与Unicode编码(码点、代码单元、基本多语言平面BMP、辅助平面、代理对)

Java字符串与Unicode编码 1. Unicode编码简介 Unicode是一个为世界上所有书写系统设计的字符编码标准。它旨在解决不同编码标准之间不兼容的问题&#xff0c;使得计算机能够处理和显示世界上几乎所有的字符。Unicode为每个字符分配了一个唯一的数字&#xff0c;称为“码点”&…

字典集合案例

1.统计字符 统计字符串中每个字符出现的次数 s l like summer very much #去掉空格 s s.replace(" ","") d dict() for i in s:if i in d:d[i] 1else:d[i] 1 for i in d:print(i,d[i]) 2.求不重复的随机数 #导入随机数 import random a int(input(&q…

自动化测试的艺术:Xcode中GUI测试的全面指南

自动化测试的艺术&#xff1a;Xcode中GUI测试的全面指南 在软件开发过程中&#xff0c;图形用户界面&#xff08;GUI&#xff09;测试是确保应用质量和用户体验的关键环节。Xcode&#xff0c;作为苹果的官方集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了一套强大…

智能疲劳驾驶检测:基于YOLO和深度学习的全流程实现

引言 疲劳驾驶是导致交通事故的重要原因之一。为了提高道路安全&#xff0c;及时检测和预警驾驶员的疲劳状态显得尤为重要。本文介绍了一种基于深度学习的疲劳驾驶检测系统。该系统利用YOLO模型&#xff08;YOLOv8/v7/v6/v5&#xff09;进行疲劳驾驶检测&#xff0c;并提供了详…

OD C卷 - 密码输入检测

密码输入检测 &#xff08;100&#xff09; 给定一个密码&#xff0c;‘<’ 表示删除前一个字符&#xff0c;输出最终得到的密码&#xff0c;并判断是否满足密码安全要求&#xff1a; 密码长度>8;至少包含一个大写字母&#xff1b;至少包含一个小写字母&#xff1b;至少…

探索若依(Ruoyi):开源的企业级后台管理系统解决方案

探索若依&#xff08;Ruoyi&#xff09;&#xff1a;开源的企业级后台管理系统解决方案 在现代企业管理中&#xff0c;拥有一个高效、稳定的后台管理系统是至关重要的。若依&#xff08;Ruoyi&#xff09;作为一款开源的企业级后台管理系统&#xff0c;为企业提供了丰富的功能…

SpringBoot中JSR303校验

JSR是 Java EE 的一种标准&#xff0c;用于基于注解的对象数据验证。在Spring Boot应用中&#xff0c;你可以通过添加注解直接在POJO类中声明验证规则。这样可以确保在使用这些对象进行操作之前&#xff0c;它们满足业务规则。个人认为非常有用的&#xff0c;因为它减少了代码中…

2.6基本算法之动态规划2989:糖果

描述 由于在维护世界和平的事务中做出巨大贡献&#xff0c;Dzx被赠予糖果公司2010年5月23日当天无限量糖果免费优惠券。在这一天&#xff0c;Dzx可以从糖果公司的N件产品中任意选择若干件带回家享用。糖果公司的N件产品每件都包含数量不同的糖果。Dzx希望他选择的产品包含的糖…

被问到MQ消息已丢失,该如何处理?

在分布式系统中&#xff0c;消息中间件&#xff08;如 RabbitMQ、RocketMQ、Kafka、Pulsar 等&#xff09;扮演着关键角色&#xff0c;用于解耦生产者和消费者&#xff0c;并确保数据传输的可靠性和顺序性。尽管我们通常会采取多种措施来防止消息丢失&#xff0c;如消息持久化、…

【Vue实战教程】之 Vue Router 路由详解

Vue Router路由 1 路由基础 1.1 什么是路由 用Vue.js创建的项目是单页面应用&#xff0c;如果想要在项目中模拟出来类似于页面跳转的效果&#xff0c;就要使用路由。其实&#xff0c;我们不能只从字面的意思来理解路由&#xff0c;从字面上来看&#xff0c;很容易把路由联想…

HTML(五)——HTML区块,布局

HTML区块 HTML可以通过 <div> 和 <span>将元素组合起来&#xff0c;可以来布局&#xff0c;就是盒子&#xff0c;div是块级盒子&#xff0c;里面 可以放任何东西&#xff0c;span里面装的是文本 HTML 区块元素 大多数 HTML 元素被定义为块级元素或内联元素。 实…

Java 面试 | Redis

目录 1. 在项目中缓存是如何使用的&#xff1f;2. 为啥在项目中要用缓存&#xff1f;3. 缓存如果使用不当会造成什么后果&#xff1f;4. redis 和 memcached 有什么区别&#xff1f;5. redis 的线程模型是什么&#xff1f;6. 为什么单线程的 redis 比多线程的 memcached 效率要…

dns逆向解析,主从服务,多域名访问(穿插ntp服务器)

复习 域名解析&#xff1a; 正向解析&#xff1a;将域名解析为ip 反向解析&#xff1a;将ip解析为域名 逆向解析 关闭防火墙和selinux&#xff0c;配置静态ip [rootdns ~]# vim /etc/named.rfc1912.zones [rootdns ~]# vim /etc/named.conf [rootdns ~]# cd /var/named/ [rootd…