Grep/awk는 여러 파일을 단일 출력으로 변환합니다.

Grep/awk는 여러 파일을 단일 출력으로 변환합니다.

grep현재 텍스트 문자열을 검색하고 awk필요한 변수를 필터링하는 데 사용하는 데이터가 포함된 여러 txt 파일이 있습니다 . 문자열이 파일에서 반복되므로 현재 이 명령을 사용하여 원하는 문자열을 추출하고 있습니다.

grep 'text' *.txt | awk ' NR==1  {print $2 } ' > outputfile

문제는 폴더의 여러 파일을 반복하고 추출된 변수를 각 파일의 단일 출력 파일에 쓰고 싶다는 것입니다. 이 질문에 대한 답변은 이전에 이미 답변된 것으로 알고 있지만 이 내용이 처음이어서 구현하는 데 어려움을 겪고 있습니다.

어떤 피드백이라도 대단히 감사하겠습니다!

답변1

각 반복의 출력을 다른 출력 파일로 리디렉션할 수 있도록 각 파일의 파일 이름을 유지하면서 bash에서 파일을 반복합니다.

예를 들면 다음과 같습니다(테스트되지 않음).

PREFIX="/tmp/outputs"   # define where to store all the outputs
mkdir -p "${PREFIX}"    # make sure the outputs dir exists

for FILE in *.txt       # get the file names you want to work on
do
  # use ${PREFIX}/${FILE} to redirect output to a 
  # file that's associated with the input
  grep 'text' "${FILE}" | awk ' NR==1 {print $2 } ' > "${PREFIX}/${FILE}"
done

답변2

.txt내가 올바르게 이해했다면 각 파일에 대해 다음을 수행 해야 합니다 .

  • 패턴이 포함된 첫 번째 줄을 찾습니다 text.
  • 이 줄에서 공백으로 구분된 두 번째 필드를 입력 파일과 관련된 이름의 파일에 씁니다.

출력 파일 이름을 구성하는 방법을 설명하지 않았습니다. 입력 파일과 동일하게 만들 .out겠지만 .txt.

쉘 루프를 사용하여 이 작업을 수행할 수 있습니다.

for x in *.txt; do
  grep 'text' -- "$x" | awk '{print $2; exit}' >"${x%.*}.out"
done

계속 읽으라고 지시하고 아무것도 하지 않는 것보다 작업이 완료된 직후 awk를 종료하는 것이 더 빠릅니다. 또 다른 가능성은 awk를 완전히 건너뛰고 쉘이 줄 분할을 수행하도록 하는 것입니다(이것이 더 빠르거나 느린지는 많은 요인에 따라 다르며 예측에 위험을 초래하지는 않습니다).

for x in *.txt; do
  grep 'text' -- "$x" | read -r first second rest && printf '%s\n' "$rest" >"${x%.*}.out"
done

또 다른 접근 방식은 모든 작업을 awk에서 수행하는 것입니다. awk는 여러 파일에서 작동할 수 있으며 awk의 출력 리디렉션을 사용할 수 있습니다. 이를 위해서는 더 적은 수의 프로세스가 필요합니다. Gawk(GNU awk)에서는 매우 간단합니다.

awk '/text/ {print $2 >substr(FILENAME, 1, length(FILENAME)-4) ".out"; nextfile}' *.txt

awk 구현이 없는 경우 nextfile다음 파일로의 변환을 수동으로 처리해야 하므로 이 접근 방식이 덜 매력적입니다(더 복잡하고 덜 효율적입니다).

awk '
    FNR==1 {first=1}
   first && /text/ {print $2 >substr(FILENAME, 1, length(FILENAME)-4) ".out"; first=0}' *.txt

관련 정보