파일 data.csv
에는 다음과 같은 데이터가 있습니다
1,avocado,mexican green fruit
1,kiwi,green fruit
1,banana,yellow fruit
1,mango,yellow fruit
데이터를 과일 카테고리로 정리하기 위해
awk -F ',' '{print >> ($3 ".csv")}' data.csv
mexican green fruit.csv
, green fruit.csv
, 3개의 파일을 생성합니다 .yellow fruit.csv
이 파일 이름의 공백을 밑줄로 바꾸고 싶습니다._
따라서 파일 이름은 mexican_green_fruit.csv
,, 이어야 합니다.green_fruit.csv
yellow_fruit.csv
awk
그렇게 하려면 이 안감의 도움이 필요해요
awk
유일한 답을 찾고 있어요
답변1
GNU awk에 대한 awk 전용 답변(OP에서 요청한 대로)은 다음과 같습니다.
awk -F',' '{print > gensub(/[[:space:]]+/,"_","g",$3) ".csv"}' data.csv
입력이 너무 작아서 "열린 파일이 너무 많음" 임계값을 초과할 수 없는 경우 POSIX awk에 대한 awk 전용 대답은 다음과 같습니다.
awk -F',' '{out=$3 ".csv"; gsub(/[[:space:]]+/,"_",out); print > out}' data.csv
"열린 파일이 너무 많음" 임계값을 초과할 가능성이 있는 경우 POSIX awk에 대한 awk 전용 대답은 다음과 같습니다.
awk -F',' '{out=$3 ".csv"; gsub(/[[:space:]]+/,"_",out); if (!seen[$3]++) printf "" > out; print >> out; close(out)}' data.csv
그러나 마지막 것은 각 쓰기에 대해 출력 파일을 닫았다가 다시 열고 $3
각 값을 메모리에 저장할 수 있다고 가정하기 때문에 속도가 느립니다. 변경된 경우에만 출력 파일을 닫아 효율성을 향상시킬 수 있습니다.
awk -F',' '$3 != prev {close(out); out=$3 ".csv"; gsub(/[[:space:]]+/,"_",out); if (!seen[$3]++) printf "" > out; prev=$3} {print >> out}' data.csv
단순히 awk를 사용하는 것이 아니라 정렬 및 자르기를 위한 DSU(장식/정렬/장식 해제) 관용구인 POSIX awk를 사용한다는 대답에 만족한다면 다음은 sort
처리 할 수 있는 모든 크기의 입력 파일에 대해 효율적이고 강력하게 작동합니다. (요청 페이징 등을 사용하여 매우 큰 파일을 처리하도록 설계되었습니다.) 그리고 출력 파일 수에 관계없이 다음을 수행합니다.
$ cat tst.sh
#!/usr/bin/env bash
awk '
BEGIN{ FS=OFS="," }
{ print $3,NR,$0 }
' "${@:-}" |
sort -t',' -k1,1 -k2,2n |
cut -d',' -f3- |
awk '
BEGIN{ FS=OFS="," }
$3 != prev {
close(out)
out = $3 ".csv"
gsub(/[[:space:]]+/,"_",out)
prev = $3
}
{ print > out }
'
$ ./tst.sh data.csv
$ head *.csv
==> data.csv <==
1,avocado,mexican green fruit
1,kiwi,green fruit
1,banana,yellow fruit
1,mango,yellow fruit
==> green_fruit.csv <==
1,kiwi,green fruit
==> mexican_green_fruit.csv <==
1,avocado,mexican green fruit
==> yellow_fruit.csv <==
1,banana,yellow fruit
1,mango,yellow fruit
DSU에 대한 자세한 내용은 다음을 참조하세요.https://stackoverflow.com/questions/71691113/how-to-sort-data-based-on-the-value-of-a-column-for-part-multiple-lines-of-af/71694367#71694367.
답변2
이는 다음과 같은 함수를 사용하여 수행할 수 있습니다.
awk -F, '
function csvfile(name) {
gsub(/[[:space:]]+/, "_", name)
return name".csv"
}
{print >> csvfile($3)}'
여기에서 각 시퀀스에 대한 하나 이상의 공백 문자(공백, 탭, cr... 포함)가 로 대체됩니다 _
.
답변3
(gnu awk 또는 이와 유사한 것을 사용하여) 다음과 같이 실행할 수 있습니다
awk -F, '{print > gensub(/ /,"_","g",$3)".csv"}' ex.csv
gensub
기능적인 것입니다sub
- 작성하기가 약간 더 쉽습니다.>
>>
이 명령을 실행하기 전에 csv를 생성하지 않는 한 그보다 더 나을 것입니다 .- 수백만 개의 서로 다른 3달러 가치가 있다면 문제가 발생할 수 있습니다.
편집하다:새로운 요구사항에 대응(실제로는 새로운 문제)
awk -F, '
NF == 0 {next}
!seen[$3]++ {print "Quantity, f..., c..." > gensub(/ /,"_","g",$3)".csv"}
{print > gensub(/ /,"_","g",$3)".csv"}
' ex.csv