Bash 스크립트 계산기 루프

Bash 스크립트 계산기 루프

일부 샘플 데이터(이름, 성, 소득, Rax 비율)가 포함된 데이터 파일이 있습니다. 계산을 좀 해야 하는데 결과를 표시할 때 루프가 되어 순서대로 표시되지 않아서 문제가 발생합니다. 예, bash를 사용해야 합니다.

예시 파일:

------------------------------------
example-file.txt:

John,Rambo,99880,2%
Elon,Musk,144000,2%
------------------------------------

테스트.배시:

#/bin/bash

FILE=example-file.txt
 
for file in $FILE;
do
    # Get income
    INCOME=$(cat $file | awk -F, '{print $3}');
    FIRSTNAME=$(cat $file | awk -F, '{print $1}');
    LASTNAME=$(cat $file | awk -F, '{print $2}');
    # Get tax rate
    RATE=$(cat $file | awk -F, '{print $4}' | sed 's/%//');

    for foo in $INCOME
    do
     if [ "$foo" -ge 80000 ] && [ "$foo" -lt 150000 ];
        then
            for faa in $foo
            do
                NETINCOME=$(printf "%'.f\n" $(echo "(($INCOME * $RATE / 100))" | bc))
            done
    fi
    echo "${FIRSTNAME} ${LASTNAME} ${NETINCOME}"
   done
done

산출:

(standard_in) 2: syntax error
(standard_in) 3: syntax error
John
Elon Rambo
Musk 288,000
(standard_in) 2: syntax error
(standard_in) 3: syntax error
John
Elon Rambo
Musk 288,000

원하는 출력:

John Rambo 1997
Elon Musk 2880

어떻게 이를 달성할 수 있나요?

답변1

awk라인에서 필드를 추출하는 데 를 사용하고 있으므로 모든 작업을 수행하도록 놔두는 것이 어떻습니까? 충분한 산술 기능이 있어야 하며 스크립트를 AWK 스크립트로 변환하는 것이 문제를 해결하는 것보다 쉬울 수 있습니다.

$ cat example-file.txt 
John,Rambo,99880,2%
Elon,Musk,144000,2%
$ awk -v FS=, '{ print $1,$2,sprintf("%i", $3 * $4 / 100) }' example-file.txt 
John Rambo 1997
Elon Musk 2880

sprintf인쇄된 숫자의 형식을 조정하려면 제공된 첫 번째 인수를 사용하십시오 .

라인을 필터링할 수도 있습니다. 예를 들어, 소득 범위에만 관심이 있다고 가정해 보겠습니다.

$ awk -v FS=, '
  80000 < $3 && $3 < 150000 {
    print $1,$2,sprintf("%i",$3 * $4 / 100)
  }'

임의의 수의 파일을 인수로 허용합니다(상한은 시스템 구성에 따라 다름. 파일이 많으면 사용 find ... -exec awk ...).

awk -v FS=, '...' file1.txt file2.txt ...

마지막으로, s를 묶지 않고 스크립트를 파일로 저장 '하고 다음과 같이 호출할 수 있습니다.

awk -v FS=, -f awk_script file1.txt

어딘가에서 리터럴을 사용해야 하는 경우를 대비해 불편한 문자열 연결이 필요하지 않습니다 '. 예를 들어 sprintf형식 문자열에 플래그를 포함하려는 경우 '인라인 스크립트는 다음과 같습니다.

awk ... '... sprintf("%'"'"'.f", $3 * $4 / 100) ...' file

답변2

스크립트에 몇 가지 문제가 있습니다. 첫째, 문자열을 배열로 취급합니다(단지 문자열이 하나인 for foo in $bar경우에는 수행할 이유나 요점이 없습니다 $bar). 둘째, 파일을 한 번만 읽으면 파일을 여러 번 읽을 수 있습니다. 셋째, 변수를 인용하지 않습니다. 즉, 파일 이름에 공백이 포함될 수 있으면 스크립트가 중단됩니다. 더 좋은 방법은 다음과 같습니다.

#/bin/bash

## take a list of file names as an argument so you can
## work on multiple files.
for file in "$@";
do

  ## get the values
  while read firstName lastName income  rate; do
    rate=${rate//%}
    if [[ "$income" -ge 80000  && "$income" -lt 150000 ]]; then
      netIncome=$(printf "%'.f\n" $(echo "($income * $rate) / 100" | bc))
    ## You didn't specify what should happen if the income isn't in the
    ## target range, so I am assuming you want it to be the $income unchanged.
    else
      netIncome=$income
    fi
    echo "$firstName $lastName $netIncome"
  done < <(awk -F, '{print $1,$2,$3,$4}' "$file")
done

파일을 인수로 사용하여 이를 실행할 수 있습니다.

$ foo.sh file
John Rambo 1,997
Elon Musk 2,880

관련 정보