이것은 질문의 확장입니다.첫 번째 열 값을 기준으로 파일을 여러 파일로 분할. 방금 가입했기 때문에 위 질문에 의견을 추가할 만큼 담당자 포인트가 부족합니다. 그래서 반복해서 사과드립니다.
다음 명령을 사용하여 파일을 첫 번째 열로 분할했습니다.
awk -F"\t" '{print>"subfolder/"$1}' inputfile
그러나 나는 하나를 얻었습니다 awk: cannot open for output (Too many open files)
.
그런 다음 명령을 다음으로 변경했습니다.
awk -F"\t" '{print>"subfolder/"$1}{close("subfolder/"$1)}' inputfile
.
그러나 파일을 닫으면 0바이트 출력 파일이 생성됩니다.
답변1
print >filename
in을 사용하면 awk
파일이 열리고 파일이 있는 경우 길이가 0으로 잘립니다. awk
그러면 그럴 것이다파일을 열어두세요프로그램이 끝날 때까지. 많은 파일에 대해 이 작업을 수행하면 알다시피 리소스 제한이 발생하게 됩니다.
당신이 해야 할 일은 close(filename)
당신의 몫 입니다 close("subfolder/"$1)
. $1
올바른 값을 유지하면서 이 작업을 수행 해야 합니다 .
그러나 이는 다음을 의미합니다.다음 print >
파일을 열고 이전 내용을 자릅니다.
이 문제를 해결하려면 print >>
대신 를 사용하십시오 print >
. 그러면 파일이 열립니다.추가.
다음 문제는 awk
프로그램을 두 번째로 실행하면 첫 번째 실행 결과가 추가된다는 점이다. 이는 프로그램을 다시 실행하기 전에 삭제하거나 이름을 바꿀 출력 파일을 구성해야 함을 의미합니다.
전체 스크립트는 다음과 같습니다.
#!/bin/sh
rm -rf subfolder # remove old output files
mkdir subfolder # and recreate output directory
awk -F '\t' '{ fname = "subfolder/" $1; print >>fname; close(fname) }' inputfile
데이터가 첫 번째 열에서 정렬된 경우 실제로 다음을 수행해야 할 때까지 파일을 닫지 않는 매우 작은 최적화의 이점을 누릴 수 있습니다.
awk -F '\t' '
fname != "subfolder/" $1 {
if (fname != "")
close(fname)
fname = "subfolder/" $1
}
{ print >>fname }' inputfile
입력이 첫 번째 필드에서 정렬되는 경우 위와 print >>
같이 변경할 수 있습니다 . print >
데이터가 정렬되지 않은 경우에도 을 사용하면 print >>
그 사이에 출력 파일을 닫았다가 다시 열 필요 없이(느릴 수 있음) 동일한 첫 번째 필드가 있는 여러 개의 연속 행을 동일한 파일에 기록합니다.
Mosvy가 의견에서 지적했듯이, 파일 이름에 다음 값을 사용하고 싶은 유혹을 느낄 수 있습니다.합리적인맹목적으로 쓰기 전에.
값에 소문자 또는 대문자 영숫자 문자(및 밑줄)만 포함되어 있는지 명시적으로 확인하여 이를 수행할 수 있습니다.
awk -F '\t' '
fname != "subfolder/" $1 {
if (fname != "")
close(fname)
fname = "subfolder/" $1
if (fname ~ /[^a-zA-Z0-9_]/) {
print "Bad filename: " fname >"/dev/stderr"
exit(1)
}
}
{ print >>fname }' inputfile
그는 또한 출력 파일에 대한 리디렉션을 처리하는 대체 방법을 제안했는데, 이는 파일이 처음 열릴 때 파일을 자르고 나중에 추가하기 위해 파일을 여는 것입니다. 그는 파일 이름을 연관 해시의 키로 저장하여 이를 수행합니다.
{
if (names[fname]++)
print >>fname
else
print >fname
}