[과제] Shell Script를 사용한 사칙연산 계산기 구현

강세준·2023년 1월 11일
0

nhn

목록 보기
1/7

기능


  1. 연산결과를 저장할 파일이 있는지 검사하고 파일이 없다면 파일을 생성한다.
  2. 연산에 사용된 숫자와 연산자 및 결과는 매 실행마다 파일에 저장된다.
  3. 숫자와 연산자를 입력받아 연산 결과를 출력한다.
  4. 숫자를 입력할때 정수인지 검사하고, 연산자는 지정한 연산자(+, -, *, /, %)인지 검사를 수행한다. 만약 조건에 일치하지 않으면 에러메세지를 띄우고 다시 입력받는다.
  5. 매 연산이 끝날때 마다 연산을 계속 수행할 것인지 YES,NO로 물어보고 다른 대답을 하면 에러메세지를 띄우고 다시 입력받도록 한다.
  6. 0으로 나누는(/, %)연산은 수행할 수 없기 때문에 에러메세지를 띄우고 다시 입력받는다.

환경


사용 언어 : bash shell script
환경 : MAC OS

설정


MAC에서는 POSIX sed를 사용하기 때문에 리눅스의 gnu sed보다 기능이 제한적이다.
따라서 MAC에 gnu sed를 설치하고 sed를 대체하게끔 환경 설정이 필요하다

  • gnu-sed설치
brew install gnu-sed
  • sed명령시 default로 gsed를 수행할 수 있게끔 경로 수정
export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"

구현


#!/usr/bin/env bash

totalSum=0
repeatFlag=1
numberCount=0
operationCount=0
inputNumber=0
fileName="calculatorResult.txt"
resultCount=1
fileLineLocation=0
  • totalSum : 연산의 결과를 저장하는 변수
  • repeatFlag : 연산을 계속 수행할 것인지 판단하는 변수
  • numberCount : 연산에 사용한 숫자의 개수를 세는 변수
  • operationCount : 연산에 사용한 연산자의 개수를 세는 변수
  • inputNumber : 입력받은 숫자를 저장하는 변수
  • fileName : 읽어오거나 저장할 파일 경로 설정하는 상수
  • resultCount : 파일에서 몇번째로 연산결과를 저장할 것인지 계산하는 변수
  • fileLineLocation : 파일에 연산 내용을 작성하기 위해 Line의 수를 구하는 변수

파일에 연산기록을 작성하기 위한 함수

fileExistCreate()

function fileExistCreate() {
if [ -f ${fileName} ]; then
        echo "file Found"
        fileLineLocation=`cat ${fileName} | wc -l | tr -d ' '`
        resultCount=$(($fileLineLocation/5+1))
else
        echo "file not Found Create New File"
fi

        echo "${resultCount} Turn Result" >> $fileName
        echo "Input Number :" >> $fileName
        echo "Input Operation :" >> $fileName
        echo "Mathematical expression :" >> $fileName
        echo " " >> $fileName
}

파일 존재여부 확인 및 서식 생성 함수


fileInputNumber()

function fileInputNumber() {
        fileInputNumberCommand=`sed -i ''"$(($fileLineLocation+2))"'s/$/ '"$1"'/' "${fileName}"`
        echo -n $fileInputNumberCommand
}

연산에 사용된 숫자들을 파일에 기록하는 함수
매개변수 $1 : 숫자(정수)


fileInputOperation()

function fileInputOperation() {
        case $1 in
                "+")
                        fileResultSyntaxCommand=`sed -i ''"$(($fileLineLocation+4))"'s/:/: (/' "${fileName}"`
                        echo -n $fileResultSyntaxCommand
                ;;
                "-")
                        fileResultSyntaxCommand=`sed -i ''"$(($fileLineLocation+4))"'s/:/: (/' "${fileName}"`
                        echo -n $fileResultSyntaxCommand
                ;;
        esac
                fileInputOperationCommand=`sed -i ''"$(($fileLineLocation+3))"'s/$/ \'"$1"'/' "${fileName}"`
                fileResultCommand=`sed -i ''"$(($fileLineLocation+4))"'s/$/ \'"$1"'/' "${fileName}"`
                echo -n $fileInputOperationCommand
                echo -n $fileResultCommand
}

연산에 사용된 연산자들을 파일에 기록하는 함수
매개변수 $1 : 연산자


fileInputNumberResult()

function fileInputNumberResult() {
        fileResultCommand=`sed -i ''"$(($fileLineLocation+4))"'s/$/ '"$2"'/' "${fileName}"`
        echo -n $fileInputNumberCommand
        case $1 in
                "+")
                        fileResultSyntaxCommand=`sed -i ''"$(($fileLineLocation+4))"'s/$/ )/' "${fileName}"`
                        echo -n $fileResultSyntaxCommand
                ;;
                "-")
                        fileResultSyntaxCommand=`sed -i ''"$(($fileLineLocation+4))"'s/$/ )/' "${fileName}"`
                        echo -n $fileResultSyntaxCommand
                ;;
        esac
}

연산 결과를 기록하는 함수
매개변수 $1 : 연산자, $2 : 숫자(정수)

사칙연산 수행을 위한 함수


InputJudge()

function inputJudge() {
        read -p "InputNumber : " inputNumber
        numberRegex="^-?[0-9]+$"
        until [[ $inputNumber =~ $numberRegex ]]; do
                echo "[Error] This is not Integer"
                read -p "InputNumber : " inputNumber
        done
}

숫자(정수)를 입력받아 inputNumber에 저장하는 함수

  • 정규표현식을 사용하여 숫자(정수)가 아니면 에러 발생 후 재입력

arithmeticJudge()

function arithmeticJudge() {
        local operation=""
        local calculateNumber
        operationRegex="^[\+|\*|\/|\%|\-]$"
        read -p "Input the arithmetic operations(+, -, *, /, %) : " operation
        until [[ $operation =~ $operationRegex ]]; do
                echo "[Error] This is not right operation"
                read -p "Input the arithmetic operations(+, -, *, /, %) : " operation
        done
        inputJudge
        calculateNumber=$inputNumber

        while [[ ($operation = "/" && $calculateNumber -eq 0)]] || [[($operation = '%' && $calculateNumber -eq 0) ]]; do
                echo "[Error] calculation isn't possible"
                inputJudge
                calculateNumber=$inputNumber
        done

        fileInputNumber $calculateNumber

        case $operation in
                "+")
                        totalSum=$(($totalSum + $calculateNumber))
                ;;
                "-")
                        totalSum=$(($totalSum - $calculateNumber))
                ;;
                "*")
                        totalSum=$(($totalSum * $calculateNumber))
                ;;
                "/")
                        totalSum=$(($totalSum / $calculateNumber))
                ;;
                "%")
                        totalSum=$(($totalSum % $calculateNumber))
                ;;
        esac
                fileInputOperation "$operation"
                fileInputNumberResult "$operation" $calculateNumber
}

연산자를 입력받아 연산 이후 계산 결과를 totalSum에 저장하는 함수

  • 정규표현식을 사용하여 지정한 연산자가 아니면 에러 발생 후 재입력
  • 0으로 나누는 경우(/,%) 에러 발생 후 재입력

repeatAnswer()

function repeatAnswer() {
        local repeatAnswer=""
        read -p "Will you stop? (YES, NO) : " repeatAnswer
        until [[ $repeatAnswer = "YES" || $repeatAnswer = "NO" ]]; do
                echo "[Error] Wrong Input"
                read -p "Will you stop? (YES, NO) : " repeatAnswer
        done
        if [ $repeatAnswer = "NO" ]; then
                repeatFlag=1
        else
                repeatFlag=0
                numberCount=$(($numberCount + 1))
        fi
}

연산을 계속 할 것인지 물어보고 조건에 맞게 repeatFlag로 변환하는 함수

  • YES, NO가 아닌 다른 입력 시 에러 발생 후 재입력

셸 스크립트 동작(main)

#main
fileExistCreate
while [ $repeatFlag -eq 1 ]; do
        numberCount=$(($numberCount + 1))
        if [ $numberCount -eq 1 ]; then
                inputJudge
                totalSum=$inputNumber
                fileInputNumber $totalSum
                fileResultCommand=`sed -i ''"$(($fileLineLocation+4))"'s/$/ '"${totalSum}"'/' "${fileName}"`
                echo -n $fileReusltCommand
        fi
        arithmeticJudge
        repeatAnswer
done
operationCount=$(($numberCount - 1))

echo " calculate result = "  $totalSum
echo " numberCount  = "  $numberCount
echo " operationCount = "  $operationCount
fileTotalResultCommand=`sed -i ''"$(($fileLineLocation+4))"'s/$/ = '"${totalSum}"'/' "${fileName}"`
echo -n $fileInputNumberCommand

각 함수들을 사용하여 사칙연산을 수행하고 파일에 기록한다.

결과

첫 실행

2번째 실행

연산 결과

cat calculatorResult.txt

profile
데이터를 탐구하는 개발자

0개의 댓글