쉘스크립트로 작성한 계산 명령

[code:2yiuy6iq]
#!/bin/sh

:<<EOF
설명:
콘솔에서 사용하는 간단한 계산기입니다.
bc를 사용하여 계산하고, 그결과를 보여줍니다.
기본적으로 소숫점19자리까지 계산합니다.
기능:
기수를 사용하여 해당 진법으로 계산가능합니다.
소숫점아래 마지막 자리로 자동 반올림합니다.


사용법
minicalc [옵션] 계산식
옵션
–ibase 기수 입력값을 해당 기수로 인식
–obase 기수 해당기수로 출력
–base 기수 간단히 입출력을 모두 해당기수로 처리
–scale 실수정밀도 해당 자릿수로 반올림하여 보여줌
EOF

#----------------------------------------------------------------------
SCALE=19
BASE=
IBASE=
OBASE=

전달된 인수 파싱

옵션과 파라미터 분석

-l은 긴 옵션으로 ','로 구분되며 ':'을 붙으면 값을 가짐을 의미하며,

명령실행시 --longopt=value 혹은 --longopt value형식으로 옵션값을 적게 됩니다.

옵션과 파라미터 사이에는 '–'로 구분됨

옵션의 값은 작은따옴표로 둘러 싸이기 떄문에 eval를 사용하여 이를 없앰

eval set – getopt -o &quot;&quot; -l &quot;base&#58;,ibase&#58;,obase&#58;,scale&#58;&quot; &quot;$@&quot;
while true; do
case "$1" in
–base) shift; BASE=$1;;
–ibase) shift; IBASE=$1;;
–obase) shift; OBASE=$1;;
–scale) shift; SCALE=$1;;
–) shift;break
esac
shift
done

BASE 변수값이 없으면 10으로 설정

base=${BASE:-10}

IBASE,OBASE 변수값이 없으면 base값으로 설정

ibase=";ibase=${IBASE:-$base}"
radix="${OBASE:-$base}"
obase=";obase=$radix"

최대 정밀도 19로 설정

[ $SCALE -gt 19 ] && SCALE=19

#(

정밀도를 하나 더하여 설정(반올림을 위해서)하고, 입출력에 사용되는 기수를 설정(주의:ibase가 설정되면 obase값도 ibase의 기수로 입력해야 하므로, obase를 먼저 설정해야함)

echo "scale=$(($SCALE+1))$obase$ibase"

계산식이 파라미터로 전달되지 않았으면, 표준입력을 재지향하고, 아니면 그대로 출력

[ -z "$" ] && cat || echo "$"

#)

계산 명령을 실행

#|bc

10진법일경우 정밀도에 따라 반올림하여 보여주고, 그외는 그대로 출력

#|( [ $radix -eq 10 ] && xargs printf "%.${SCALE}g\n" || cat)
(
echo "scale=$(($SCALE+1))$obase$ibase";
[ -z "$" ] && cat || echo "$"
)
|bc
|( [ $radix -eq 10 ] && xargs printf "%.${SCALE}g\n" || cat)
[/code:2yiuy6iq]

minicalc 2 * 3 이런 형식으로 하면 "*"가 모든 파일명으로 인식됩니다.
이는 bash의 glob(와일드카드와 비슷함)기능으로 명령이 실행될때 파일명으로 치환이 되어 버립니다.
그래서 minicalc 2 * 3 이렇게 사용하셔야 됩니다.

이것을 피하고, 편하게 사용하고 싶으시다면…
~/bin/.bash_aliases에
alias minicalc=‘set -o noglob;source ~/bin/minicalc’
이렇게 적어 놓고, minicalc파일의 마지막에 set +o noglob라고 추가로 적으시면 됩니다.

오… 뭔가 재밌는 코드 같아용.

수고하셨습니다. :)

[quote="protochaos":3dwlhgw5]
이것을 피하고, 편하게 사용하고 싶으시다면…
~/bin/.bash_aliases에
alias minicalc=‘set -o noglob;source ~/bin/minicalc’
이렇게 적어 놓고, minicalc파일의 마지막에 set +o noglob라고 추가로 적으시면 됩니다.[/quote:3dwlhgw5]

혹시 이부분에 대하여 좀더 설명을 부탁드릴수 있나요?

다른 스크립트에서도 이를 어떻게 응용할수 있는지를 알고 싶습니다.

가령… 저의 경우에는 '스페이스’입력할때가 귀찮은 경우가 많은데 이를 이용해

스패이스 입력을 안해도 되게끔 할수 있는지가 궁금하네요.

이건 그런게 아니구요…
ls * 하면 모든 파일들이 출력되자나요?
그런데 minical 2 * 3이라고 입력하면…
파라미터가 2 모든파일명 3 이런형태로 minical에게 전달된다는 것입니다.
원하는 것은 *를 모든파일이 아니라 곱하기 기호로 인식하고 싶은거니까.

*를 모든파일로 인식하지 못하게 하는게…
set -o noglob 명령이고요… 이것이 한번 실행되어야… 다음부터 *를 문자그대로 인식하게 되기때문에…
;으로 구분하여 실행하게 한것입니다.

그러나 이렇게 설정되면…
ls *하면 *라는 파일이 없다고 나옵니다. 이것이 glob가 해제되어 생기는 문제니까…
일시적으로 noglob상태로 만들어놓고, minicalc를 실행하고,
끝나면… 다시 glob 기능을 켜는것이죠.
그러나 source 명령없이 set +o noglob를 스크립트 내부에서 실행하게되면…
이건 다른 bash쉘에서 실행되기 때문에… 해당 쉘에서만 적용됩니다.
그래서 source명령으로 서브프로세스에서 실행되는것이 아니라…
현재쉘에서 실행되게 한것입니다.

그리고, 스페이스를 입력하기 귀찮다면…
echo " " | mycmd
이런 형태로 사용하면 되지 않겠습니까?
그걸 쉽게하는 명령이 yes입니다.

yes " "|mycmd 이렇게 사용하면 mycmd가 실행될때 표준입력에 계속 공백문자를 넣습니다.
mycmd가 종료되면 yes도 끝나게 되죠.

만약 줄바꿈문자를 넣고 싶다면
yes $‘\n’|mycmd 이렇게 하시면 되죠.

[quote="protochaos":3luwoj6t]

yes $‘\n’|mycmd 이렇게 하시면 되죠.[/quote:3luwoj6t]

아하…! 그렇군요.

설명 감사드립니다.^^