String 防止在';对于循环';
我必须编写一个bash脚本来忽略变量中的特定字符串,以防止文件混淆。我对bash非常陌生,不知道如何编写一行代码来检查非法的变量/字符串组合 例如,字符串String 防止在';对于循环';,string,bash,for-loop,variables,String,Bash,For Loop,Variables,我必须编写一个bash脚本来忽略变量中的特定字符串,以防止文件混淆。我对bash非常陌生,不知道如何编写一行代码来检查非法的变量/字符串组合 例如,字符串大理石和火成岩不应在For循环中一起使用。这是需要更改的代码: #!/bin/bash IGNEOUS_BLOCK=(aa adakite pahoehoe) METAMORPHIC_BLOCK=(eclogite marble) SEDIMENTARY_BLOCK=(argillite chalk jaspillite) ROCK_
大理石
和火成岩
不应在For循环中一起使用。这是需要更改的代码:
#!/bin/bash
IGNEOUS_BLOCK=(aa adakite pahoehoe)
METAMORPHIC_BLOCK=(eclogite marble)
SEDIMENTARY_BLOCK=(argillite chalk jaspillite)
ROCK_TYPE=(igneous_rocks metamorphic_rocks sedimentary_rocks)
#Buttons
for igneous_block in "${IGNEOUS_BLOCK[@]}" ; do
for rock_type in "${ROCK_TYPE[@]}" ; do
printf "{
\"parent\": \"block/button\",
\"textures\": {
\"texture\": \"strata:blocks/"$rock_type"/"$igneous_block"\"
}
}"> "${igneous_block}_button.json"
done;
done;
这就是它应该做的:
如果变量岩石类型
使用字符串火成岩
则应仅拾取火成岩块
内部的字符串,而不是从变质岩块
和沉积岩块
这就是我希望所有变量都起作用的原因:
ROCK_TYPE
循环使用可用的字符串
ROCK_TYPE=(igneous_rocks metamorphic_rocks sedimentary_rocks)
火成岩块
只能使用字符串火成岩
IGNEOUS_BLOCK=(aa adakite pahoehoe)
METAMORPHIC_BLOCK=(aa adakite pahoehoe)
SEDIMENTARY_BLOCK=(aa adakite pahoehoe)
变质岩块
仅允许使用管柱变质岩
IGNEOUS_BLOCK=(aa adakite pahoehoe)
METAMORPHIC_BLOCK=(aa adakite pahoehoe)
SEDIMENTARY_BLOCK=(aa adakite pahoehoe)
沉积岩块
只能使用管柱沉积岩
IGNEOUS_BLOCK=(aa adakite pahoehoe)
METAMORPHIC_BLOCK=(aa adakite pahoehoe)
SEDIMENTARY_BLOCK=(aa adakite pahoehoe)
我的代码需要做哪些更改才能像我希望的那样工作?您似乎想要嵌套数据,其中
ROCK\u TYPE
是一个类型数组,每个类型都有一个子类型数组
在真正的编程语言中,可以使用嵌套的数据结构,这将使这变得非常容易,但不幸的是,Bash只有一个真正用于模拟嵌套数据的结构
相反,您可以使用语句定义要迭代的块数组:
#!/bin/bash
rock_types=(igneous_rocks metamorphic_rocks sedimentary_rocks)
for rock_type in "${rock_types[@]}"; do
case $rock_type in
igneous_rocks)
blocks=(aa adakite pahoehoe)
;;
metamorphic_rocks)
blocks=(eclogite marble)
;;
sedimentary_rocks)
blocks=(argillite chalk jaspillite)
;;
esac
for block in "${blocks[@]}"; do
echo "$rock_type/$block"
done
done
输出:
火成岩/aa
火成岩/埃达克岩
火成岩/火成岩
变质岩/榴辉岩
变质岩/大理岩
沉积岩/泥板岩
沉积岩/白垩
沉积岩/碧玉岩
顺便说一句,所有caps变量名称都应该为环境变量(如PATH
)和其他特殊变量(如RANDOM
)保留
- OP希望在岩石类型数组中列出的所有岩石类型中循环
- 每个岩石类型和匹配的*\u块数组都有匹配的名称,a)数组名称都是大写的,b)字符串
替换为岩石
块
一种相对简单的方法是使用
case
语句根据当前岩石类型确定要引用哪个**\u块体数组
验证想法的第一步:
for rtype in "${ROCK_TYPE[@]}"
do
echo "+++++ rock type = ${rtype}"
case "${rtype}" in
igneous_rocks) printf "%s\n" "${IGNEOUS_BLOCK[@]}" ;;
metamorphic_rocks) printf "%s\n" "${METAMORPHIC_BLOCK[@]}" ;;
sedimentary_rocks) printf "%s\n" "${SEDIMENTARY_BLOCK[@]}" ;;
esac
done
由此产生:
+++++ rock type = igneous_rocks
aa
adakite
pahoehoe
+++++ rock type = metamorphic_rocks
eclogite
marble
+++++ rock type = sedimentary_rocks
argillite
chalk
jaspillite
.igneous_rocks.igneous_block.aa.
.igneous_rocks.igneous_block.adakite.
.igneous_rocks.igneous_block.pahoehoe.
.metamorphic_rocks.metamorphic_block.eclogite.
.metamorphic_rocks.metamorphic_block.marble.
.sedimentary_rocks.sedimentary_block.argillite.
.sedimentary_rocks.sedimentary_block.chalk.
.sedimentary_rocks.sedimentary_block.jaspillite.
有几种方法可以修改它,以允许在关联的*\u块数组中循环各个值,例如:
for rtype in "${ROCK_TYPE[@]}"
do
bname=${rtype//rocks/block} # OPs example could use this for the 'texture' field and json file name
for btype in $(case "${rtype}" in
igneous_rocks) echo "${IGNEOUS_BLOCK[@]}" ;;
metamorphic_rocks) echo "${METAMORPHIC_BLOCK[@]}" ;;
sedimentary_rocks) echo "${SEDIMENTARY_BLOCK[@]}" ;;
esac)
do
echo ".${rtype}.${bname}.${btype}."
done
done
由此产生:
+++++ rock type = igneous_rocks
aa
adakite
pahoehoe
+++++ rock type = metamorphic_rocks
eclogite
marble
+++++ rock type = sedimentary_rocks
argillite
chalk
jaspillite
.igneous_rocks.igneous_block.aa.
.igneous_rocks.igneous_block.adakite.
.igneous_rocks.igneous_block.pahoehoe.
.metamorphic_rocks.metamorphic_block.eclogite.
.metamorphic_rocks.metamorphic_block.marble.
.sedimentary_rocks.sedimentary_block.argillite.
.sedimentary_rocks.sedimentary_block.chalk.
.sedimentary_rocks.sedimentary_block.jaspillite.
注意:句点作为可视分隔符添加
另一个想法是使用
nameref
(即,一个变量的值用作另一个变量的名称)
注意:我包括了这个选项,因为示例显示了类似命名的岩石类型和块体名称,这反过来使得nameref
解决方案相对容易实现
考虑以下(简单)示例:
或者:
$ unset x h
$ x=5
$ typeset -n h=x # define nameref
$ echo $x
5
$ echo $h
5
$ x=10
$ echo $h
10
使用nameref
s解决岩石/块体问题的一个想法:
for rtype in "${ROCK_TYPE[@]}"
do
bname=${rtype//rocks/block} # again, use this for the 'texture' field and json file name
typeset -u -n currblock=${rtype//rocks/BLOCK} # define nameref, convert to all uppercase and replace 'rocks' with 'BLOCK'
for btype in "${currblock[@]}" # loop through nameref'd values
do
echo ".${rtype}.${bname}.${btype}."
done
done
它生成与案例
解决方案相同的输出集:
.igneous_rocks.igneous_block.aa.
.igneous_rocks.igneous_block.adakite.
.igneous_rocks.igneous_block.pahoehoe.
.metamorphic_rocks.metamorphic_block.eclogite.
.metamorphic_rocks.metamorphic_block.marble.
.sedimentary_rocks.sedimentary_block.argillite.
.sedimentary_rocks.sedimentary_block.chalk.
.sedimentary_rocks.sedimentary_block.jaspillite.
注意:同样,作为可视分隔符添加的句点包含以下代码:
IGNEOUS_BLOCK=(aa adakite pahoehoe)
METAMORPHIC_BLOCK=(eclogite marble)
SEDIMENTARY_BLOCK=(argillite chalk jaspillite)
ROCK_TYPE=(igneous_rocks metamorphic_rocks sedimentary_rocks)
for i in "${ROCK_TYPE[@]}"; do
# convert to upercase, replace rocks
n="${i//_rocks/_BLOCK}"
n="${n^^}[@]"
# Using indirect expansion
for j in "${!n}"; do
echo "$i/$j"
done
done
将输出:
igneous_rocks/aa
igneous_rocks/adakite
igneous_rocks/pahoehoe
metamorphic_rocks/eclogite
metamorphic_rocks/marble
sedimentary_rocks/argillite
sedimentary_rocks/chalk
sedimentary_rocks/jaspillite
注意:按照惯例,大写变量用于导出变量,如PWD行列UID EID TERM LC_ALL COUNTRY HISTSIZE等。希望在脚本中使用小写变量
您可以使用与数组元素相同的方式命名变量,从而避免使用某些代码:
igneous_rocks=(aa adakite pahoehoe)
metamorphic_rocks=(eclogite marble)
sedimentary_rocks=(argillite chalk jaspillite)
rock_types=(igneous_rocks metamorphic_rocks sedimentary_rocks)
for i in "${rock_types[@]}"; do
n="${i}[@]"
for j in "${!n}"; do
echo "$i/$j"
done
done
作为间接扩展的替代方案,还有一个namereference
而不是使用bash/shell生成客户机数据文件,因为它不是非常可移植且难以维护,这迟早会让您感到不快,因为它是另一个要添加到构建环境中的框架和工具集 您最好使用Minecraft Forge项目记录的专用Gradle任务实现数据生成器: 如果你还真的想用bash做这件事。如果使用nameref变量动态引用相应的岩石类型数组,则代码可以工作:
#/usr/bin/env bash
#shellcheck disable=SC2034#已使用nameref
火成岩=('aa''埃达克岩''pahoehoe')
#shellcheck disable=SC2034#已使用nameref
变质岩=(‘榴辉岩’‘大理石’)
#shellcheck disable=SC2034#已使用nameref
沉积岩=(‘泥板岩’‘白垩岩’‘碧玉岩’)
岩石类型=(‘火成岩’‘变质岩’‘沉积岩’)
#钮扣
声明-n岩石类型
对于“${rock_types[@]}”中的rock_type;做
对于“${rock_type[@]}”中的rock_名称;做
cat“${rock\u name}\u button.json”
完成
完成
两个用于
和执行
,但只有一个完成
?添加一个shebang,然后将您的脚本粘贴到那里:我将代码更改为完成两个而不是一个,并在顶部添加了一个shebang,但我仍然在“aa”边使用了“沉积岩”。我该怎么解决?继续检查。shebang不应该缩进,双引号是错误的。但这似乎不是问题所在,在bash中执行代码似乎完全没问题。ShellCheck只推荐编写代码的替代方案。这些文件确实会像应该的那样生成,但代码中使用的字符串顺序是错误的。此外,双引号可以以多种方式使用。我还发现,大部分代码都可以用双引号或单引号括起来。是的,我问,为什么变量不命名为火成岩=(aa adakite pahoehoe)
,而是一些随机的火成岩块
?您为什么要将火成岩
转换为火成岩块
?为什么不在f中命名变量火成岩