줄 수가 다른 3개의 파일이 있습니다. 세 개의 파일을 반복하면서 각 파일의 첫 번째 줄을 새 파일인 output1.txt로 인쇄한 다음 각 파일의 두 번째 줄을 또 다른 새 파일인 output2.txt로 인쇄하려고 합니다. 각 파일에는 줄 수가 다르기 때문에 file2 및 file3에 대한 항목이 없는 줄이 여러 개 있는 경우 이를 무시하고 이후 생성되는 출력 파일에 아무것도 인쇄하지 않아야 합니다. Bash에서 어떻게 이를 달성할 수 있나요?
파일 1
xyz
abc
def
ghi
jkl
파일 2
123
456
789
파일 3
ax1
by2
결과물 파일
출력1.txt
xyz
123
ax1
출력2.txt
abc
456
by2
출력3.txt
def
789
출력4.txt
ghi
출력5.txt
jkl
답변1
bash
이를 수행하려면 Tell을 사용하세요 awk
. 이것이 바로 bash의 목적입니다(예를 들어 텍스트 처리 자체를 수행하는 대신).
예를 들어, 다음 awk 한 줄 문은 FNR
리터럴 문자열 "output", 현재 입력 파일의 현재 줄 번호(awk 변수) 및 리터럴 문자열 ".txt"로 구성된 파일 이름에 각 입력 줄을 씁니다.
$ awk '{print > "output" FNR ".txt"}' file*
$ tail output*
==> output1.txt <==
xyz
123
ax1
==> output2.txt <==
abc
456
by2
==> output3.txt <==
def
789
==> output4.txt <==
ghi
==> output5.txt <==
jkl
참고: 출력 파일 수가 많으면(수백 개 이상) 문제가 발생할 수 있습니다. 일부 버전의 awk에서는 커널 및 로그인 환경에서 프로세스에 허용된 파일 핸들 수를 초과하면 프로세스가 오류와 함께 종료될 수 있습니다. 다른 버전의 awk(예: GNU awk)를 사용하면 특정 순간에 쓰기 위해 열려 있는 파일 핸들을 관리할 때 속도가 느려질 수 있습니다. 입력 파일 중 일부가 수백 줄 길이가 아닌 한 이는 문제가 되지 않을 것입니다.
다음은 모든 버전의 awk 및 모든 길이의 입력 파일에서 작동하지만(한 번에 쓰기를 위해 하나의 출력 파일만 열기 때문에) 훨씬 느려집니다.왜냐하면각 쓰기에 대한 출력 파일을 열고 쓰기 후에 즉시 닫습니다. 그럼에도 불구하고 셸에서 수행하는 것보다 여전히 몇 배 더 빠릅니다.
awk '{
# use 5-digit zero-padded output filenames for this version
# e.g. output00001.txt
out = sprintf("output%05i.txt", FNR);
if (out in files) {
# we have written to this file before, so append to it
print >> out
} else {
# first write to this file, so create or truncate it.
print > out
files[out]=1
}
close(out)
}' file*
답변2
동료가 제안한 다음 솔루션이 저에게 효과적이었습니다. 시간을 내어 내 질문에 답변해 주신 모든 분들께 감사드립니다. 정말 감사해요.
# for flattening and merging the file and writing to a tempfile
pr -J -m -t file* --sep-string=';' > mergedfile
# Now you have data in each line which can be looped and redirected to respective filenames based on the loop count
# No.of files will be equal to the biggest file in the input, in this case , you will see 240 files
i=1
while read line; do
echo "=======file no: $i ========"
echo $line|sed -e 's@^;@@g' -e 's@;;@@g'|tr ';' '\n' > output${i}.txt
let i=i+1
done < mergedfile