일부 샘플 데이터(이름, 성, 소득, 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