그래서 내 목표는 .csv 파일에서 여러 값을 인쇄하는 것입니다. 나는 스크립트를 실행하는 데 가능한 가장 짧은 시간을 들여 가능한 한 빨리 이 작업을 수행할 수 있는 방법을 찾으려고 노력하고 있습니다.
예를 들어 "test.csv"라는 파일이 있습니다. "test.csv"에는 다음 값이 있습니다.
0,1673466134,875601111928832,3336977422,22610058C2740,2020-06-03,19:00:01,103,456123489478512
0,6987507655,226102200333225,2312147777,226102E1858F0,2020-06-02,19:00:04,102,112323548998726
0,7891328975,250423212127644,7421354899,22610058C5350,2020-06-01,19:00:00,103,123123489784238
1,1324654889,784502311776287,4778994563,22610058C351E,2020-06-09,19:00:01,102,489123478941324
0,1231324474,247122410577385,1232498779,22610058C53A0,2020-06-07,19:00:00,104,123498715234789
1,4471222598,226912478523771,4123487987,226102C242C40,2020-06-04,19:00:00,103,789123418971354
다음 값을 인쇄해야 합니다.
예: 첫 번째 열에서 "1"인 모든 값을 계산하려면 다음을 수행합니다.
cat test1.csv | awk -F ',' '{print $1}' | awk '/^1/' | wc -l
예 : 1열 = 1인 8열의 모든 값을 합산
cat test1.csv | awk -F ',' '{print $1,$8}' | awk '/^1/' | awk '{sum+=$2} END {print sum}'
그리고 그러한 예는 셀 수 없이 많습니다. 위와 같이 실행해야 하는 명령이 약 11개 있습니다. 내 목표는 이러한 모든 명령을 스크립트 파일에 포함하고 가능한 한 빨리 실행하는 것입니다.
나는 다음과 같은 스크립트를 만들었습니다.
#!/bin/bash
while IFS=, read col_1 col_2 col_3 col_4 col_5 col_6 col_7 col_8 col_9
do
echo "No of lines containing 0 on the 1st column: "
awk -F ',' '{print $1}' | awk '/^0/' | wc -l
echo "No of lines containing 1 on the 1st column:"
awk -F ',' '{print $1}' | awk '/^1/' | wc -l
done < test.csv
내가 겪고 있는 문제는 첫 번째 명령을 실행한 후 내가 무엇을 하든 두 번째 명령이 "0"을 표시한다는 것입니다.
누구든지 이 문제를 해결하도록 도와줄 수 있나요? 감사합니다!
답변1
글쎄, 우선, 당신은 이것을하고 싶지 않습니다. awk는 쉘보다 훨씬 빠르므로 awk 스크립트를 쉘 스크립트로 변환해도 이점이 없습니다! 셸은 잊어버리고 모든 작업을 awk에서 수행하세요. 이 파일을 다음과 같이 저장하십시오 foo.awk
.
#!/bin/awk -f
BEGIN{
FS=","
}
{
if($1~/^0/){zeros++}
if($1~/^1/){ones++}
}
END{
printf "No of lines containing 0 on the 1st column: %d\n", zeros;
printf "No of lines containing 1 on the 1st column: %d\n", ones;
}
다음 명령을 사용하여 파일을 실행 가능하게 만든 chmod a+x foo.awk
후 실행하십시오.
/path/to/foo.awk /path/to/test.csv
예제 데이터에 대해 실행하면 다음과 같은 결과를 얻습니다.
$ foo.awk test.csv
No of lines containing 0 on the 1st column: 4
No of lines containing 1 on the 1st column: 2
두 번째 예에 명령을 포함하려면 다음을 수행하십시오.
#!/bin/awk -f
BEGIN{
FS=","
}
{
if($1~/^0/){zeros++}
if($1~/^1/){ones++; sum8+=$8}
}
END{
printf "No of lines containing 0 on the 1st column: %d\n", zeros;
printf "No of lines containing 1 on the 1st column: %d\n", ones;
printf "Sum of all 8th fields where the 1st field starts with 1: %d\n", sum8
}
어떤 이유로 쉘 스크립트를 사용해야 한다면 쉘 스크립트가 awk를 실행하도록 두고 다른 작업은 수행하지 마십시오. 셸에서 입력을 분할하려고 하지 마세요. 복잡하고 매우 느립니다. 다음과 같은 것이 훨씬 좋습니다.
#!/bin/bash
awk -F"," '($1~/^0/){zeros++}
($1~/^1/){ones++}
END{
printf "No of lines containing 0 on the 1st column: %d\n", zeros;
printf "No of lines containing 1 on the 1st column: %d\n", ones;
}' "$1"
마지막으로, 이것을 별도의 명령으로 유지하려면 다음과 같이 할 수 있지만 파일을 여러 번 읽어야 하므로 속도가 매우 느려집니다.
#!/bin/bash
echo "No of lines containing 0 on the 1st column: "
awk -F ',' '{print $1}' "$1" | awk '/^0/' | wc -l
echo "No of lines containing 1 on the 1st column:"
awk -F ',' '{print $1}' "$1" | awk '/^1/' | wc -l
echo "Sum of all the 8th columns where the 1st column starts with 1:"
awk -F ',' '/^1/{sum+=$8} END {print sum}' "$1"
그런 다음 파일을 실행 가능하게 만들고( chmod a+x /path/to/foo.sh
) 다음과 같이 실행할 수 있습니다.
/path/to/foo.sh /path/to/test.csv