Bash: 여러 파일을 반복하고 각 파일의 각 줄을 인쇄하고 다른 파일에 씁니다.

Bash: 여러 파일을 반복하고 각 파일의 각 줄을 인쇄하고 다른 파일에 씁니다.

줄 수가 다른 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

관련 정보