hh:mm:ss를 비교하기 위해 Solaris 상자에 구성된 IF

hh:mm:ss를 비교하기 위해 Solaris 상자에 구성된 IF

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 <

솔라리스 상자에서 무엇을 변경해야 하는지 제안해 주시겠습니까?

답변1

<표준 연산자가 아님test/[..](아래 인용문 참조). Bash, Dash, busybox 등에서는 지원되는 것 같지만 Zsh에서는 지원되지 않는 것 같습니다(Ksh의 다른 버전에 대해서는 잘 모르겠습니다). Bash, ksh 및 Zsh도 지원됩니다(이스케이프 필요 없음). 이들 중 하나를 지원하는 쉘을 찾아서 사용해야 합니다.[[ str1 < str2 ]]<

(알아채다Solaris 10 및 이전 버전에는 POSIX 이전 버전도 있었습니다./bin/sh, 이는 어떤 의미에서도 표준이 아니기 때문에 중요하지 않습니다. )

새로 발명되었거나 KornShell에서 나온 일부 추가 기본 명령은 조건부 명령의 일부로 초기 제안에 나타났습니다([[]]): s1>s2, s1<s2,...다음으로 전달되지 않습니다.시험조건부 명령이 아직 포함되지 않았기 때문에 쉘에서 제거될 때의 유틸리티시험역사적 구현에 내장된 유틸리티유용.

답변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:locale과 동일한 정렬 순서) 로케일을 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보다 작은 것으로 취급되거나 그렇지 않은 것으로 간주된다는 것을 의미합니다.10strcmp()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

/usr/xpg4/bin어쨌든, 솔라리스에서는 늘 그렇듯, 이전 버전인지 확인해야 합니다. /bin그렇지 /usr/bin않으면 $PATH쓸모없는 비표준 유틸리티를 사용하게 될 것입니다. 특히, /bin/awkSolaris에서는 위의 코드가 작동하지 않습니다. 이것은 1970년대의 것입니다. 아니요 ARGV.

#!/bin/sh같은 이유로 she-bang에 사용하고 싶지 않습니다 . Solaris의 Standard/POSIX는 sh다음과 같습니다 /usr/xpg4/bin/sh(Solaris 11에서는 /bin/shBourne 셸에서 ksh93으로 변경되어 POSIX와 더욱 호환됩니다. 또한 /usr/xpg4/bin/sh많은 적합성 버그가 있다는 점에 유의하세요).

답변4

최근 Solaris 시스템[1]에서는 /bin/sh그렇습니다. ksh93따라서 다음을 수행해야 합니다:

if [[ "$lag" < "$MAX_LAG" ]]; then ..

[[ .. ]]내부적으로 사용되는 경우 이중 괄호에 유의 하세요 [[ .. ]].<사전 편찬의 비교에서는 유사한 문자열 ksh에 대해 작동합니다 .HH:MM:SS

쉘이 실제로 이것을 지원하지 않으면 cannon을 사용할 수 있습니다.

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솔라리스에서는ksh93 솔라리스 11부터 시작.

관련 정보