최소 / 최대 두 숫자를 제공하는 유닉스 명령이 있습니까? 찾고있었습니다 stdin. 나는 그 목적을 위해 작은 스크립트를

에서 읽은 숫자를 제한하는 명령을 찾고있었습니다 stdin.

나는 그 목적을 위해 작은 스크립트를 작성했지만 (평판은 환영한다), 이것에 대한 표준 명령이 간단하고 일반적인 사용 사례가 아닌지 궁금했다.

최소 두 개의 숫자 를 찾는 내 스크립트 :

#!/bin/bash
# $1 limit

[ -z "$1" ] && { echo "Needs a limit as first argument." >&2; exit 1; }

read number

if [ "$number" -gt "$1" ]; then
        echo "$1"
else
        echo "$number"
fi


답변

다음과 dc같이 두 숫자 만 비교할 수 있습니다 .

dc -e "[$1]sM $2d $1<Mp"

… 여기서 "$1"최대 값 "$2"은보다 작은 경우 인쇄 할 숫자 "$1"입니다. 또한 GNU가 필요 dc하지만 다음과 같이 똑같이 할 수 있습니다.

dc <<MAX
    [$1]sM $2d $1<Mp
MAX

위의 두 경우 모두에서 당신은 0 이외의 정밀도를 설정할 수 있습니다 (기본값) 등이 ${desired_precision}k. 모두를 위해 당신이 두 값이 있는지 확인하는 것도 필수적입니다 숫자가 확실히 있기 때문에 dc할 수 system()w / 호출 !연산자.

다음의 작은 스크립트 (및 다음 스크립트 ) 를 사용하면 입력을 확인해야 grep -v \!|dc합니다. 임의의 입력을 강력하게 처리 할 수있는 것입니다. 또한 dc음수는 _접두어가 아닌 접두사로 해석 -합니다. 후자는 빼기 연산자이기 때문입니다.

그 외에도이 스크립트를 사용 dc하면 제공 할 수있는만큼 많은 연속 \newline으로 구분 된 숫자를 읽고 $maxwo 중 작은 값에 따라 값 또는 입력 각각에 대해 인쇄합니다 .

dc -e "${max}sm
       [ z 0=? d lm<M p s0 lTx ]ST
       [ ? z 0!=T q ]S?
       [ s0 lm ]SM lTx"

그래서 … 그 각각의 [사각 괄호 ]한 확대는 것입니다 dc 문자열 입니다 오브젝트 S어느 하나 – 각각의 배열에 각각 aved T, ?또는이 M. 문자열 로 할 수 dc있는 몇 가지 다른 것 외에도 매크로로 예리하게 만들 수 있습니다 . 제대로 배치하면 완벽하게 작동하는 작은 스크립트가 간단하게 조립됩니다.xdc

dc스택 에서 작동합니다 . 모든 입력 객체는 각각 마지막에 쌓입니다. 각각의 새로운 입력 객체는 마지막 상단 객체와 그 아래에있는 모든 객체가 추가 될 때마다 스택 아래로 아래로 밀립니다. 객체에 대한 대부분의 참조는 최상위 스택 값에 대한 것이며 대부분의 참조 는 스택의 최상위를 나타 냅니다 (아래에있는 모든 객체를 1 씩 끌어옵니다) .

메인 스택 외에도 (적어도) 256 개의 어레이가 있으며 각 어레이 요소에는 자체 스택이 제공됩니다. 나는 여기서 많이 사용하지 않습니다. 내가 할 수 있습니다 언급 한 바와 같이 그냥 문자열을 저장하기 l원하는 경우를 OAD 및 전자 x조건부 ecute을, 나는 s찢어 $max의 상단에서의 값을 m배열입니다.

어쨌든,이 작은 부분은 dc주로 쉘 스크립트가하는 일을 수행합니다. 일반적으로 표준 입력에서 매개 변수를 가져 오는 -e것처럼 GNU-ism 옵션을 사용 dc하지만 다음과 같이 수행 할 수 있습니다.

echo "$script" | cat - /dev/tty | dc

$script위 비트처럼 보이면.

다음과 같이 작동합니다.

  • lTx-이것은 상단에 저장된 매크로를 l무효화하고 xecutes T (테스트를 위해, 나는 보통 그 이름을 임의로 선택합니다) .
  • z 0=?T동부 표준시 다음 w 스택 깊이를 테스트 / z스택이 비어있는 경우, 그리고 (0 객체를 보유하고 읽기) 가 호출 ?매크로를.
  • ? z0!=T q?매크로는 ? dcstdin에서 입력 라인을 읽는 내장 명령의 이름을 따서 명명 되었지만, 또 다른 z스택 깊이 테스트를 추가 q하여 빈 줄을 가져 오거나 EOF에 도달하면 전체 작은 프로그램을 사용할 수 있습니다 . 그러나 !스택을 채우지 않고 대신 성공적으로 T채우면 est를 다시 호출 합니다.
  • d lm<MTEST는 것이다 d스택의 상단과 uplicate과 비교 $max (에 저장된 m) . 경우 m적은 값이, dc부르는 M매크로를.
  • s0 lmM스택의 상단을 팝하여 더미 스칼라에 덤프합니다 0-스택을 팝하는 저렴한 방법입니다. 또한 est 로 돌아 가기 전에 다시 l소리를냅니다 .mT
  • p– 경우에 것을이 수단 m스택의 현재 정상보다 적은 다음, m그것을 대체 합니다 ( d어쨌든, 그것의 uplicate)을 여기에있다 printed는 다른이와 어떤 입력이되어 있었다하지 않는 p대신 rinted.
  • s0-나중에 ( p스택을 팝하지 않기 때문에 ) 스택 상단을 0다시 덤프 한 다음 …
  • lTx– 반복적으로 lOAD T추정 한 번 더 한 후 전자 xecute을 다시.

따라서이 작은 조각을 실행하고 대화식으로 터미널 dc에서 숫자를 입력하고 입력 한 숫자 또는 $max입력 한 숫자가 더 큰 경우 값을 인쇄 할 수 있습니다. 또한 모든 파일 (예 : 파이프) 을 표준 입력으로 받아들입니다. 빈 줄이나 EOF가 나타날 때까지 읽기 / 비교 / 인쇄 루프를 계속합니다.

그래도 이것에 대한 몇 가지 참고 사항-쉘 함수의 동작을 에뮬레이트하기 위해 이것을 작성 했으므로 한 줄에 하나의 숫자 만 강력하게 처리합니다. dc그러나 한 줄에 많은 수의 공백으로 분리 된 숫자를 처리 할 수 ​​있습니다. 그러나 스택으로 인해 줄의 마지막 숫자가 첫 번째 dc줄이되어 줄어 듭니다. 따라서 한 줄에 두 개 이상의 숫자를 인쇄 / 입력하면 출력이 역으로 인쇄됩니다. 그것을 처리하는 것은 배열에 줄을 저장 한 다음 작동시키는 것입니다.

이처럼 :

dc -e "${max}sm
    [ d lm<M la 1+ d sa :a z0!=A ]SA
    [ la d ;ap s0 1- d sa 0!=P ]SP
    [ ? z 0=q lAx lPx l?x ]S?
    [q]Sq [ s0 lm ]SM 0sa l?x"

그러나 … 나는 그것을 아주 깊이 설명하고 싶을 지 모른다. 로 말할 것으로 충분 dc스택 그것을 저장 값 또는 하나의 각 값을 판독 $max다시 한번 비어있는 스택을 검출하면, 그 후 다른을 판독하기 전에 각각의 인덱스 오브젝트를 인쇄 인덱스 배열에서의 값, 및 입력 라인.

그리고 첫 번째 스크립트는 수행하는 동안 …

10 15 20 25 30    ##my input line
20
20
20
15
10                ##see what I mean?

두 번째는 :

10 15 20 25 30    ##my input line
10                ##that's better
15
20
20                ##$max is 20 for both examples
20

k명령으로 먼저 설정하면 임의의 정밀도 부동 소수점을 처리 할 수 ​​있습니다 . 또한 input 또는 output radices를 독립적으로 변경할 수 있습니다. 때로는 예상치 못한 이유로 유용 할 수 있습니다. 예를 들면 다음과 같습니다.

echo 100000o 10p|dc
 00010

… 먼저 dc출력 기수를 100000으로 설정 한 다음 10을 인쇄합니다.


답변

두 개의 정수 a와를 다루는 것을 알고 있다면 삼항 연산자를 사용하는b 간단한 쉘 산술 확장으로 숫자를 최대로 지정할 수 있습니다 .

$(( a > b ? a : b ))

숫자 분 :

$(( a < b ? a : b ))

예 :

$ a=10
$ b=20
$ max=$(( a > b ? a : b ))
$ min=$(( a < b ? a : b ))
$ echo $max
20
$ echo $min
10
$ a=30
$ max=$(( a > b ? a : b ))
$ min=$(( a < b ? a : b ))
$ echo $max
30
$ echo $min
20
$

이것을 보여주는 쉘 스크립트가 있습니다 :

#!/usr/bin/env bash
[ -z "$1" ] && { echo "Needs a limit as first argument." >&2; exit 1; }
read number
echo Min: $(( $number  < $1 ? $number : $1 ))
echo Max: $(( $number  > $1 ? $number : $1 ))

답변

sort그리고 head이것을 할 수 있습니다 :

numbers=(1 4 3 5 7 1 10 21 8)
printf "%d\n" "${numbers[@]}" | sort -rn | head -1       # => 21

답변

미리 정의 된 수학 함수 라이브러리를 정의한 bc다음 명령 줄에서 사용할 수 있습니다.

예를 들어, 다음과 같은 텍스트 파일에 다음을 포함하십시오 ~/MyExtensions.bc.

define max(a,b){
  if(a>b)
  {
   return(a)
  }else{
   return(b)
  }
}

이제 다음으로 전화 할 수 있습니다 bc.

> echo 'max(60,54)' | bc ~/MyExtensions.bc
60

참고로, 온라인에서 사용할 수 있는 무료 수학 라이브러리 기능 있습니다.

이 파일을 사용하면 GCD다음 과 같은보다 복잡한 함수를 쉽게 계산할 수 있습니다 .

> echo 'gcd (60,54)' | bc ~/extensions.bc -l
6

답변

댓글이 너무 깁니다 :

예를 들어 sort | head또는 sort | tail콤보로 이러한 작업을 수행 할 수 있지만 리소스 및 오류 처리 측면에서 다소 차선적인 것 같습니다. 실행과 관련하여 콤보는 두 줄을 확인하기 위해 두 개의 프로세스를 생성하는 것을 의미합니다. 약간 과잉 인 것 같습니다.

더 심각한 문제는 대부분의 경우 입력이 제정신이며 숫자 만 포함한다는 사실을 알아야합니다. @glennjackmann의 솔루션printf %d 은 이것을 정수로 해결합니다 . 형식 지정자를로 변경하지 않으면 %f반올림 문제가 발생할 수 있습니다.

test $1 -gt $2 비교 실패 여부를 알려줍니다 (종료 상태 2는 테스트 중에 오류가 발생했음을 의미합니다. 일반적으로 셸이 내장되어 있으므로 추가 프로세스가 생성되지 않습니다. 그러나 더 빠른 실행. 정수에서만 작동합니다.

몇 개의 부동 소수점 숫자를 비교해야하는 경우 흥미로운 옵션은 다음과 bc같습니다.

define x(a, b) {
    if (a > b) {
       return (a);
    }
    return (b);
 }

test $1 -gt $2쉘에서 in을 사용 하는 것과 같습니다 .

max () { printf '
    define x(a, b) {
        if (a > b) {
           return (a);
        }
        return (b);
     }
     x(%s, %s)
    ' $1 $2 | bc -l
}

여전히 printf | sort | head두 숫자 보다 거의 2.5 배 빠릅니다 .

에서 GNU 확장을 사용할 수 있다면이 함수를 bc사용 read()하여 숫자를 bcsript 로 직접 읽을 수도 있습니다 .


답변

$ a 및 $ b의 더 큰 값을 얻으려면 다음을 사용하십시오.

[ "$a" -gt "$b" ] && $a || $b

그러나 그 주위에 무언가가 필요합니다. 아마도 숫자를 실행한다는 의미는 아니므로 두 가지 사용 “에코”의 더 큰 값을 표시하려면

[ "$a" -gt "$b" ] && echo $a || echo $b

위의 예는 쉘 기능에 잘 맞습니다.

max() {
   [ "$1" -gt "$2" ] && echo $1 || echo $2
}

둘 중 큰 값을 변수에 지정하려면 다음 수정 된 버전을 사용하십시오.

[ "$a" -gt "$b" ] && biggest=$a || biggest=$b

또는 정의 된 기능을 사용하십시오.

biggest=$( max $a $b )

기능 변형은 또한 입력 오류 검사를 깔끔하게 추가 할 수있는 기회를 제공합니다.

소수점 이하 두 자리의 최대 소수를 반환하려면 다음을 사용할 수 있습니다. awk

decimalmax() {
   echo $1 $2 | awk '{if ($1 > $2) {print $1} else {print $2}}';
}

편집 :이 기술을 사용하면 편집 / 노트에 따라 다른 방식으로 작동하는 “제한”기능을 만들 수 있습니다. 이 함수는 둘 중 더 낮은 값을 반환합니다. 예 :

limit() {
   [ "$1" -gt "$2" ] && echo $2 || echo $1
}

유틸리티 함수를 별도의 파일에 넣고 호출하여 다음 myprogram.funcs과 같이 스크립트에서 사용하고 싶습니다 .

#!/bin/bash

# Initialization. Read in the utility functions
. ./myprogram.funcs

# Do stuff here
#
[ -z "$1" ] && { echo "Needs a limit as first argument." >&2; exit 1; }

read number
echo $( limit $1 $number )

FWIW 이것은 여전히 ​​당신이 한 일을하고 있으며, 더 장황하지만 버전은 효율적입니다.

더 컴팩트 한 형태는 실제로는 좋지 않지만 스크립트에서 혼란을 방지합니다. 간단한 if-then-else-fi 구문이 많은 경우 스크립트가 빠르게 확장됩니다.

하나의 스크립트에서 더 크거나 작은 수의 검사를 여러 번 다시 사용하려면 함수에 넣으십시오. 함수 형식을 사용하면 디버그 및 재사용이 쉬워지고 정수가 아닌 10 진수를 처리 할 수있는 awk 명령과 같이 스크립트의 해당 부분을 쉽게 바꿀 수 있습니다.

단일 사용 사례 인 경우 인라인으로 코딩하면됩니다.


답변

함수를 다음과 같이 정의 할 수 있습니다

maxnum(){
    if [ $2 -gt $1 ]
    then
        echo $2
    else
        echo $1
    fi
}

로 호출하면 maxnum 54 42에코 54됩니다. 원하는 경우 함수 내에 유효성 검사 정보 (예 : 두 개의 인수 또는 숫자를 인수로 추가)를 추가 할 수 있습니다.