IF 在 Solaris 框中构造以比较 hh:mm:ss

IF 在 Solaris 框中构造以比较 hh:mm:ss

我创建了下面的脚本,它对 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 工具箱中,exprawk可用于比较字符串。

两者都用于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/binin$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/shksh93,因此应该执行以下操作:

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 开始

相关内容