Bash - 存储在变量中的文本作为参数时无法识别
Bash - Text stored in variable is not recognized when put it as argument
我正在尝试制作一个脚本来自动下载 SpigotMC BuildTools,检测输入版本 (sh build.sh <version>
),并设置一个变量,如果版本大于或等于 1.14(自此版本以来) , SpigotMC 默认停止自动编译 craftbukkit 的自动化。现在它只编译 spigot jar,我需要将它们都编译用于我的个人目的。)
这是我尝试过的方法(我是 Linux 新手,所以这可能会搞砸):
#!/bin/bash
# Sources:
# Append variables in bash : https://www.cyberciti.biz/faq/howto-linux-unix-bash-append-textto-variables/
# Check MANIFEST.MF content from jar file : https://www.manongdao.com/q-106728.html
# Check for specified property json file :
# https://www.ultralinux.org/post/json-bash/
# Bash Array : https://unix.stackexchange.com/questions/253892/syntax-error-unexpected-when-creating-an-array
# #######################################################################################################################################
#
# #######################################################################################################################################
# BuildTools Jar Info Variables
# -----------------------------
# BuilsTools working directory
buildtools_root="$(pwd)" # We use $(command) to store "command" output in a variable. We use ${command} if we have to stick other strings near it without whitespace.
# BuildTools jar location
buildtools_jar="$buildtools_root/BuildTools.jar"
# Current BuildTools jar version
buildtools_ver="$(unzip -p "$buildtools_jar" META-INF/MANIFEST.MF | grep 'Implementation-Version:' | cut -d '-' -f 5)"
# Jenkins Api-related variables.
# A. Retrieve BuildTools lastSuccessfulBuild link
targetJar="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.artifacts[].relativePath')"
lastSuccessfulBuild="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.url')"
# B. Make the download link
latestBuildToolsUrl="${lastSuccessfulBuild}artifacts/$targetJar"
# Latest BuildTools Build Version
latestBuildToolsVersion="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.number')"
displayFullName="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.fullDisplayName')"
# ---------------------------------------------------------------------------------------------------------------------------------------
# BuildTools Jar Run Variables
# -----------------------------
#
# #######################################################################################################################################
# This is a function to set java home to current java version in use.
javahome_set () {
JAVA_HOME=$(dirname "$(dirname "$( readlink -f /etc/alternatives/java )")")
OIFS=$IFS
IFS=':';
for i in $VAR;
do
JAVA1=$i/bin/java
JAVA2=$i/java
if [ -d "$i" ];
then
if [ ! -L "$JAVA1" ] && [ -x "$JAVA1" ] || [ ! -L "$JAVA2" ] && [ -x "$JAVA2" ]; then
echo "dropping path: $i";
else
NEW=$NEW:$i
fi
fi
done
IFS=$OIFS
JAVA_HOME=$NEW:$JAVA_HOME/bin
JAVA_HOME=${JAVA_HOME#:*}
}
javahome_set
# This function requires arguments. Checks if >=
vercomp () {
if [[ == ]]
then
return 0
fi
local IFS=.
local i ver1=() ver2=()
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}
# This is a function to download the latest BuildTools version and check if download is successful.
buildtools_download () {
curl --silent "$latestBuildToolsUrl" --output BuildTools.jar #Request download to BuildTools.
if [ "$?" -eq 0 ]; then #Check if file was downloaded. It returns error code non-zero if file was not properly downloaded. (in this language)
echo "$Green Successful downloaded BuildTools.$Color_Off"
else
echo "$Red Error while downloading BuildTools. $Color_Off"
fi
}
# This is a function to check for updates for BuildTools jar
buildtools_check () {
if [ ! -e "$buildtools_jar" ]; then #If BuildTools.jar does NOT exist in "BuildTools" folder
echo "$Yellow Downloading BuildTools..."
buildtools_download
exit
elif [ -e "$buildtools_jar" ]; then
if [ "$buildtools_ver" -lt "$latestBuildToolsVersion" ]; then
echo "$Blue Updating BuildTools... $Color_Off"
rm "$buildtools_jar"
buildtools_download
fi
else
echo "$Cyan BuildTools is up to date. $Color_Off"
fi
}
info_menu () {
echo "==============================================[Local-Info]=============================================="
echo "BuildTools Root : $buildtools_root"
echo "Executable Path : $buildtools_jar"
echo "Installed Version : $buildtools_ver"
echo "JAVA_HOME Directory : $JAVA_HOME"
echo "=============================================[JsonAPI-Info]============================================="
echo "Latest Download Url: $latestBuildToolsUrl"
echo "========================================================================================================"
echo
if [ "$buildtools_ver" -eq "$latestBuildToolsVersion" ]; then
echo "$Green You have the latest SpigotMC BuildTools version. $Color_Off"
else
echo "$Yellow A new build is available : $displayFullName"
fi
echo
}
if [ -z "" ]; then
echo "$BCyan Usage: [=11=] $BBlue<version> $Color_Off" & exit #By default, [=11=] is the name of this file
else
if [ -d "" ]; then #If argument is defined
if [ "" = "latest" ]; then
buildtools_check
else
vercomp "" "1.14"
if [ $? -eq 0 -o $? -eq 1 ]; then
BothJars=(--compile craftbukkit,spigot) # means >= 1.14 ; sets the $BothJars variable
buildtools_check
fi
if [ "" -lt "1.14" ]; then
echo "$Yellow You want to build an older server version. Good choice btw."
buildtools_check
fi
fi
fi
rm -rf "" && mkdir ""
cd "" || exit
java -jar ./BuildTools.jar --rev "" "${BothJars[@]}" --generate-source --generate-docs #../filename is for executing it from one dir far.
我已经添加了评论,以便您了解发生了什么。
有人可以帮我解决这个问题吗?
编辑:如果您曾经玩过 Minecraft,或者如果您看过不同 版本 的 Minecraft,您可能会遇到以下版本格式:
1.7.10 ; 1.8; 1.13.2 ; 1.14; 1.15.3(不,没有“1.8.0”版本。只有“1.8”)
以下是 tr
命令后数学错误版本之间的比较示例:
1.8 > 1.7.10
- 18 > 1710
1.14 > 1.13.2
- 114 > 1132
1.15.2 < 1.16
- 1152 < 116
所以...可能存在影响这些数字比较的问题,因为它们是版本,而不是分数或整数。
编辑 2:我不会进行超过 3 次编辑/post。感谢 Richard K. 帮助我实现版本检查功能!我重写了我的脚本以使其更完整。我将重要的部分存储在函数中以节省 space 并更加可见。
摘要:我不明白我在这里做错了什么。 U_U
编辑 3:根据 Rachid K 的回答,我对这部分进行了测试:
#!/bin/bash
vercomp () {
if [[ == ]]
then
return 0
fi
local IFS=.
local i ver1=() ver2=()
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}
if [ -z "" ]; then
echo "$BCyan Usage: [=12=] $BBlue<version> $Color_Off" & exit #By default, [=12=] is the name of this file
else
if [ -d "" ]; then #If argument is defined
if [ "" = "latest" ]; then
echo "Building latest version"
else
vercomp "" "1.14"
rc=$?
case $rc in
0)
echo " You want to build version 1.14"
;;
1)
echo " You want to build version above 1.14"
;;
2)
echo " You want to build version below 1.14"
;;
latest)
echo " You want to build latest version."
;;
esac
fi
fi
fi
因此 vercomp()
应该查看是否:$1 等于最新的字符串; $1 大于或等于 1.14 ; $1 低于 1.14。
功能看起来不错,但是echo命令不显示。我注意到在某些情况下,由于缺少双引号,echo 命令不会显示。所以......把它放在它上面。但它不起作用。为什么?
显然,您获得的版本要么是像 1.14 这样的数字,要么是“最新”字符串。您需要拆分检查两个测试。首先检查“最新”值:
if [ "" = "latest" ]
如果为假,请使用此post
中提出的解决方案检查版本
vercomp () {
if [[ == ]]
then
return 0
fi
local IFS=.
local i ver1=() ver2=()
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}
因此,要比较版本,只需执行以下操作:
vercomp "" "1.14"
rc=$?
case $rc in
0) echo '=';;
1) echo '>';;
2) echo '<';;
esac
我没有在任何地方看到 $BCyan
和 $BMagenta
变量定义,所以只有空白文本而不是它们。
第 7 行条件的问题是您正在比较两个字符串值,但实际上您想要比较实数(或字符串“最新”)。对于实数,最好使用 bc
实用程序。这是等同于您要执行的操作的代码(我认为):
if [ `echo ">=1.14"|bc` -eq 1 ] || [ == "latest" ]; then
我正在尝试制作一个脚本来自动下载 SpigotMC BuildTools,检测输入版本 (sh build.sh <version>
),并设置一个变量,如果版本大于或等于 1.14(自此版本以来) , SpigotMC 默认停止自动编译 craftbukkit 的自动化。现在它只编译 spigot jar,我需要将它们都编译用于我的个人目的。)
这是我尝试过的方法(我是 Linux 新手,所以这可能会搞砸):
#!/bin/bash
# Sources:
# Append variables in bash : https://www.cyberciti.biz/faq/howto-linux-unix-bash-append-textto-variables/
# Check MANIFEST.MF content from jar file : https://www.manongdao.com/q-106728.html
# Check for specified property json file :
# https://www.ultralinux.org/post/json-bash/
# Bash Array : https://unix.stackexchange.com/questions/253892/syntax-error-unexpected-when-creating-an-array
# #######################################################################################################################################
#
# #######################################################################################################################################
# BuildTools Jar Info Variables
# -----------------------------
# BuilsTools working directory
buildtools_root="$(pwd)" # We use $(command) to store "command" output in a variable. We use ${command} if we have to stick other strings near it without whitespace.
# BuildTools jar location
buildtools_jar="$buildtools_root/BuildTools.jar"
# Current BuildTools jar version
buildtools_ver="$(unzip -p "$buildtools_jar" META-INF/MANIFEST.MF | grep 'Implementation-Version:' | cut -d '-' -f 5)"
# Jenkins Api-related variables.
# A. Retrieve BuildTools lastSuccessfulBuild link
targetJar="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.artifacts[].relativePath')"
lastSuccessfulBuild="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.url')"
# B. Make the download link
latestBuildToolsUrl="${lastSuccessfulBuild}artifacts/$targetJar"
# Latest BuildTools Build Version
latestBuildToolsVersion="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.number')"
displayFullName="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.fullDisplayName')"
# ---------------------------------------------------------------------------------------------------------------------------------------
# BuildTools Jar Run Variables
# -----------------------------
#
# #######################################################################################################################################
# This is a function to set java home to current java version in use.
javahome_set () {
JAVA_HOME=$(dirname "$(dirname "$( readlink -f /etc/alternatives/java )")")
OIFS=$IFS
IFS=':';
for i in $VAR;
do
JAVA1=$i/bin/java
JAVA2=$i/java
if [ -d "$i" ];
then
if [ ! -L "$JAVA1" ] && [ -x "$JAVA1" ] || [ ! -L "$JAVA2" ] && [ -x "$JAVA2" ]; then
echo "dropping path: $i";
else
NEW=$NEW:$i
fi
fi
done
IFS=$OIFS
JAVA_HOME=$NEW:$JAVA_HOME/bin
JAVA_HOME=${JAVA_HOME#:*}
}
javahome_set
# This function requires arguments. Checks if >=
vercomp () {
if [[ == ]]
then
return 0
fi
local IFS=.
local i ver1=() ver2=()
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}
# This is a function to download the latest BuildTools version and check if download is successful.
buildtools_download () {
curl --silent "$latestBuildToolsUrl" --output BuildTools.jar #Request download to BuildTools.
if [ "$?" -eq 0 ]; then #Check if file was downloaded. It returns error code non-zero if file was not properly downloaded. (in this language)
echo "$Green Successful downloaded BuildTools.$Color_Off"
else
echo "$Red Error while downloading BuildTools. $Color_Off"
fi
}
# This is a function to check for updates for BuildTools jar
buildtools_check () {
if [ ! -e "$buildtools_jar" ]; then #If BuildTools.jar does NOT exist in "BuildTools" folder
echo "$Yellow Downloading BuildTools..."
buildtools_download
exit
elif [ -e "$buildtools_jar" ]; then
if [ "$buildtools_ver" -lt "$latestBuildToolsVersion" ]; then
echo "$Blue Updating BuildTools... $Color_Off"
rm "$buildtools_jar"
buildtools_download
fi
else
echo "$Cyan BuildTools is up to date. $Color_Off"
fi
}
info_menu () {
echo "==============================================[Local-Info]=============================================="
echo "BuildTools Root : $buildtools_root"
echo "Executable Path : $buildtools_jar"
echo "Installed Version : $buildtools_ver"
echo "JAVA_HOME Directory : $JAVA_HOME"
echo "=============================================[JsonAPI-Info]============================================="
echo "Latest Download Url: $latestBuildToolsUrl"
echo "========================================================================================================"
echo
if [ "$buildtools_ver" -eq "$latestBuildToolsVersion" ]; then
echo "$Green You have the latest SpigotMC BuildTools version. $Color_Off"
else
echo "$Yellow A new build is available : $displayFullName"
fi
echo
}
if [ -z "" ]; then
echo "$BCyan Usage: [=11=] $BBlue<version> $Color_Off" & exit #By default, [=11=] is the name of this file
else
if [ -d "" ]; then #If argument is defined
if [ "" = "latest" ]; then
buildtools_check
else
vercomp "" "1.14"
if [ $? -eq 0 -o $? -eq 1 ]; then
BothJars=(--compile craftbukkit,spigot) # means >= 1.14 ; sets the $BothJars variable
buildtools_check
fi
if [ "" -lt "1.14" ]; then
echo "$Yellow You want to build an older server version. Good choice btw."
buildtools_check
fi
fi
fi
rm -rf "" && mkdir ""
cd "" || exit
java -jar ./BuildTools.jar --rev "" "${BothJars[@]}" --generate-source --generate-docs #../filename is for executing it from one dir far.
我已经添加了评论,以便您了解发生了什么。
有人可以帮我解决这个问题吗?
编辑:如果您曾经玩过 Minecraft,或者如果您看过不同 版本 的 Minecraft,您可能会遇到以下版本格式:
1.7.10 ; 1.8; 1.13.2 ; 1.14; 1.15.3(不,没有“1.8.0”版本。只有“1.8”)
以下是 tr
命令后数学错误版本之间的比较示例:
1.8 > 1.7.10
- 18 > 1710
1.14 > 1.13.2
- 114 > 1132
1.15.2 < 1.16
- 1152 < 116
所以...可能存在影响这些数字比较的问题,因为它们是版本,而不是分数或整数。
编辑 2:我不会进行超过 3 次编辑/post。感谢 Richard K. 帮助我实现版本检查功能!我重写了我的脚本以使其更完整。我将重要的部分存储在函数中以节省 space 并更加可见。 摘要:我不明白我在这里做错了什么。 U_U
编辑 3:根据 Rachid K 的回答,我对这部分进行了测试:
#!/bin/bash
vercomp () {
if [[ == ]]
then
return 0
fi
local IFS=.
local i ver1=() ver2=()
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}
if [ -z "" ]; then
echo "$BCyan Usage: [=12=] $BBlue<version> $Color_Off" & exit #By default, [=12=] is the name of this file
else
if [ -d "" ]; then #If argument is defined
if [ "" = "latest" ]; then
echo "Building latest version"
else
vercomp "" "1.14"
rc=$?
case $rc in
0)
echo " You want to build version 1.14"
;;
1)
echo " You want to build version above 1.14"
;;
2)
echo " You want to build version below 1.14"
;;
latest)
echo " You want to build latest version."
;;
esac
fi
fi
fi
因此 vercomp()
应该查看是否:$1 等于最新的字符串; $1 大于或等于 1.14 ; $1 低于 1.14。
功能看起来不错,但是echo命令不显示。我注意到在某些情况下,由于缺少双引号,echo 命令不会显示。所以......把它放在它上面。但它不起作用。为什么?
显然,您获得的版本要么是像 1.14 这样的数字,要么是“最新”字符串。您需要拆分检查两个测试。首先检查“最新”值:
if [ "" = "latest" ]
如果为假,请使用此post
中提出的解决方案检查版本vercomp () {
if [[ == ]]
then
return 0
fi
local IFS=.
local i ver1=() ver2=()
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}
因此,要比较版本,只需执行以下操作:
vercomp "" "1.14"
rc=$?
case $rc in
0) echo '=';;
1) echo '>';;
2) echo '<';;
esac
我没有在任何地方看到
$BCyan
和$BMagenta
变量定义,所以只有空白文本而不是它们。第 7 行条件的问题是您正在比较两个字符串值,但实际上您想要比较实数(或字符串“最新”)。对于实数,最好使用
bc
实用程序。这是等同于您要执行的操作的代码(我认为):
if [ `echo ">=1.14"|bc` -eq 1 ] || [ == "latest" ]; then