我创建了下面的脚本,它对 hh:mm:ss 格式变量进行比较。
#!/bin/sh
lag=00:00:00
MAX_LAG=00:05:00
echo $lag
echo $MAX_LAG
if [ "$lag" \< "$MAX_LAG" ]
##if [ "$lag" -lt "$MAX_LAG" ]
##if [ "$lag" -lt "$MAX_LAG" ]
then
echo "No LAG found."
else
echo "LAG more than $MAX_LAG was found."
fi
在 Linux 盒子中运行时,该脚本给了我正确的输出
[test@sandboxtest02 ~]$ ./testhh.sh
00:00:00
00:05:00
No LAG found.
但是当我在Solaris框中运行相同的脚本时,该脚本给了我错误,
% sh test.sh
00:00:00
00:05:00
test.sh: test: unknown operator <
有什么建议需要在solaris box中进行更改吗?
答案1
<
不是标准运算符test
/[..]
(见下面的报价)。它似乎受 Bash、Dash、busybox 等支持,但显然不受 Zsh 支持(我不确定 Ksh 的不同版本)。 Bash、ksh 和 Zsh 也将支持(无需转义)。您必须找到并使用支持其中一种的 shell。[[ str1 < str2 ]]
<
(注意Solaris 10 及更早版本甚至有 pre-POSIX/bin/sh
,这并不重要,因为它无论如何都不是标准的。)
新发明的或来自 KornShell 的一些附加初选作为条件命令的一部分出现在早期提案中([[]]): s1>s2, s1<s2,...它们没有结转到测试当条件命令被从 shell 中删除时的实用程序,因为它们尚未包含在测试实用程序内置于历史实现中嘘公用事业。
答案2
有一些调整可以使其在 Solaris-sh 中工作;这是我的方法:
#!/bin/sh
lag=00:06:00
MAX_LAG=00:05:00
IFS=:
set -f
set -- $lag
lagtotal=`expr 3600 * $1 + 60 * $2 + $3`
set -- $MAX_LAG
maxlag=`expr 3600 * $1 + 60 * $2 + $3`
if [ "$lagtotal" -lt "$maxlag" ]
then
echo "No LAG found."
else
echo "LAG more than $MAX_LAG was found."
fi
(请注意,严格小于比较与您的“LAG更多的比 ...”)
答案3
在 POSIX 工具箱中,expr
和awk
可用于比较字符串。
两者都用于strcoll()
比较(与sort
:区域设置的整理顺序相同),但您可以将区域设置设置为 C 以获得strcmp()
比较类型。对于 HH:MM:SS 这样的事情来说,无论如何都没关系。
if expr "$time1" '<' "$time2" > /dev/null; then
printf '%s\n' "$time1 was before $time2"
fi
现在,这对于 HH:MM:SS 来说并不重要,但在一般情况下,请注意,expr
如果操作数是十进制整数,则将进行数字比较,否则将进行字符串比较。这意味着例如2
将被视为小于10
即使strcmp()
或strcoll()
否则会说。
另外,expr
如果操作数是运算符,则会失败expr
:
$ x=+ y=-; expr "$x" '<' "$y"
expr: syntax error
您可以通过在操作数前添加一些前缀来解决这两个问题,以防止它们被视为数字或运算符:
expr "x $x" '<' "x $y"
对于awk
,您也有类似的问题。你需要:
awk 'BEGIN{exit(!(""ARGV[1] < ""ARGV[2]))}' "$x" "$y"
确保比较是字符串比较而不是数字比较。
您可以使用辅助函数,例如:
compare() {
expr "x $1" "$2" "x $3"
}
或者:
compare() {
awk 'BEGIN{exit(!(""ARGV[1] '"$2"' ""ARGV[2]))}' "$1" "$3"
}
并用作:
if compare "$time1" '<' "$time2"; then
printf '%s\n' "$time1 was before $time2"
fi
无论如何,与往常一样,在 Solaris 上,您需要确保/usr/xpg4/bin
是 before/bin
和/usr/bin
in$PATH
否则您将得到过时的非标准实用程序。特别是,/bin/awk
在 Solaris 上,上述代码无法工作。这是 70 年代的一款,没有ARGV
。
出于同样的原因,你不想#!/bin/sh
在你的 she-bang 中使用。 Solaris 上的标准/POSIXsh
是/usr/xpg4/bin/sh
(尽管在 Solaris 11 中,/bin/sh
从 Bourne shell 更改为 ksh93,这使其更加符合 POSIX;还要注意,它/usr/xpg4/bin/sh
有许多一致性错误)。
答案4
在最近的 Solaris 系统[1] 上,/bin/sh
是ksh93
,因此应该执行以下操作:
if [[ "$lag" < "$MAX_LAG" ]]; then ..
注意双括号[[ .. ]]
;当在内部使用时[[ .. ]]
,<
操作员将执行词典编纂的中的比较ksh
,这应该适用于那些HH:MM:SS
类似的字符串。
如果你的 shell 确实不支持这一点,你可以使用大炮:
trim(){ ifs=IFS; IFS=:; v=$1; set -- $2; eval "$v=$1$2$3"; IFS=$ifs; }
trim a "$lag"
trim b "$MAX_LAG"
if [ "$a" -lt "$b" ]; then ..
[1]/bin/sh
在Solaris 上是ksh93
从 Solaris 11 开始。