对于cigs.sh - 完整的脚本可以在这里找到- 我编写了以下丑陋(但完美工作)逻辑来打印和格式化脚本的输出,部分只是为了找出所有边缘情况,但也因为我没有看到任何其他选择。
...
if [[ $W -le 0 && $D -le 0 && $H -eq 1 ]]; then string="$H hour"
elif [[ $W -le 0 && $D -le 0 && $H -gt 1 ]]; then string="$H hours"
elif [[ $W -le 0 && $D -eq 1 && $H -le 0 ]]; then string="$D day"
elif [[ $W -le 0 && $D -eq 1 && $H -eq 1 ]]; then string="$D day and $H hour"
elif [[ $W -le 0 && $D -eq 1 && $H -gt 1 ]]; then string="$D day and $H hours"
elif [[ $W -le 0 && $D -gt 1 && $H -le 0 ]]; then string="$D days"
elif [[ $W -le 0 && $D -gt 1 && $H -eq 1 ]]; then string="$D days and $H hour"
elif [[ $W -le 0 && $D -gt 1 && $H -gt 1 ]]; then string="$D days and $H hours"
elif [[ $W -eq 1 && $D -le 0 && $H -le 0 ]]; then string="$W week"
elif [[ $W -eq 1 && $D -le 0 && $H -eq 1 ]]; then string="$W week and $H hour"
elif [[ $W -eq 1 && $D -le 0 && $H -gt 1 ]]; then string="$W week and $H hours"
elif [[ $W -eq 1 && $D -eq 1 && $H -le 0 ]]; then string="$W week and $D day"
elif [[ $W -eq 1 && $D -gt 1 && $H -le 0 ]]; then string="$W week and $D days"
elif [[ $W -eq 1 && $D -eq 1 && $H -eq 1 ]]; then string="$W week, $D day and $H hour"
elif [[ $W -eq 1 && $D -eq 1 && $H -gt 1 ]]; then string="$W week, $D day and $H hours"
elif [[ $W -eq 1 && $D -gt 1 && $H -eq 1 ]]; then string="$W week, $D days and $H hour"
elif [[ $W -eq 1 && $D -gt 1 && $H -gt 1 ]]; then string="$W week, $D days and $H hours"
elif [[ $W -gt 1 && $D -le 0 && $H -le 0 ]]; then string="$W weeks"
elif [[ $W -gt 1 && $D -le 0 && $H -eq 1 ]]; then string="$W weeks and $H hour"
elif [[ $W -gt 1 && $D -le 0 && $H -gt 1 ]]; then string="$W weeks and $H hours"
elif [[ $W -gt 1 && $D -eq 1 && $H -le 0 ]]; then string="$W weeks and $D day"
elif [[ $W -gt 1 && $D -gt 1 && $H -le 0 ]]; then string="$W weeks and $D days"
elif [[ $W -gt 1 && $D -eq 1 && $H -eq 1 ]]; then string="$W weeks, $D day and $H hour"
elif [[ $W -gt 1 && $D -eq 1 && $H -gt 1 ]]; then string="$W weeks, $D day and $H hours"
elif [[ $W -gt 1 && $D -gt 1 && $H -eq 1 ]]; then string="$W weeks, $D days and $H hour"
elif [[ $W -gt 1 && $D -gt 1 && $H -gt 1 ]]; then string="$W weeks, $D days and $H hours"
fi
colour1='\033[0;31m'
colour2='\033[0;32m'
if (($elapsed < threshold))
then echo -e "${colour1}It's been $string since you last bought a $item."
else
echo -e "${colour2}It's been $string since you last bought a $item."
fi
也许我只是很笨,但是像上面的代码一样尴尬,我看不出有更好的方法可以重写它。是否存在,如果存在,它是什么?
另一种方法是从冗长的详细版本开始,并使用匹配模式将其修剪以删除复数等。我不知道它是否更受欢迎,因此可能更难维护。
这使用 bash 的参数扩展语法,其中
${parameter/pattern/replacement}
尝试匹配 glob 模式,如果找到则替换它。这用于“修复”“1 周”之类的“错误”,使其变为“1 周”。为了避免也匹配21 weeks
,初始字符串在开头有一个额外的空格,所以空格可以在模式中以确保只有“1”匹配。${parameter#pattern}
如果在参数的开头找到匹配项,则语法将删除该匹配项。这用于删除“0 周”。${parameter%pattern}
如果在参数末尾找到匹配项,语法将删除该匹配项。这用于删除“和 0 小时”。其他修复如果在开头或结尾留下空格,则删除空格,如果在结尾留下逗号,如果在开头留下空格,则删除“and”和空格。如果字符串中没有“and”,则最后一行将逗号替换为“and”。例如,这对应于将“2 周 3 天”更改为“2 周 3 天”,我们已经删除了“0 小时”。
如果您在 bash 下运行脚本,这个怎么样(基于 Jeff Zeitlin 的评论):
警告:这几乎需要 bash。zsh 也有数组,但是它对条目进行不同的编号(从 1 而不是 0 开始),所以最后一部分在 zsh 下会奇怪地失败。
在 bash 有
[[ ]]
表达式之前的日子里,case语句被大量用于模式匹配。if 的列表可以转换为单个 case 语句(+
符号只是一个任意分隔符):这仍然很难消化,但是如果我们将复数单词与变量保持为
s
或不分开,则该case
语句要简单得多:Bash支持函数,所以不妨试试函数。我(用伪代码)勾勒出一个可能的策略。
"s" 很容易处理,因为只有当值为 1 时它才应该是单数。逗号和“and”是基于计数的决定,因此一个函数返回一个空字符串或“正确复数”的字符串,下一个函数用于根据字符串的空性质增加一个计数器。
然后使用计数器来操作两个分隔符字符串,然后整个事情就被盲目地组装起来。
伪代码: