여러 파일에서 텍스트 문자열을 추출하고 싶은데 어떻게 루프를 실행할 수 있나요?

여러 파일에서 텍스트 문자열을 추출하고 싶은데 어떻게 루프를 실행할 수 있나요?

나는 수천 개의 .xyz파일을 가지고 있는데, 모두 같은 디렉토리에 숫자 데이터가 있습니다. 그 중 일부는 끝에 "END"라는 텍스트 문자열이 있습니다. grep원래 파일 이름 끝에 무언가를 추가하면서 "END"가 제거되고 새 파일이 생성되도록 명령을 반복하는 방법을 잘 모르겠습니다 .

내 파일 중 일부의 마지막 몇 줄 예

-1.10949170 55.68890280 -67.60000000
-0.92807500 55.64095280 -89.80000000
-0.95770560 55.66495830 -82.40000000
-0.90995000 55.63676110 -94.00000000
-1.03738890 55.65107220 -70.20000000
END

많은 파일에서 END를 제거하고 싶습니다.

-1.10949170 55.68890280 -67.60000000
-0.92807500 55.64095280 -89.80000000
-0.95770560 55.66495830 -82.40000000
-0.90995000 55.63676110 -94.00000000
-1.03738890 55.65107220 -70.20000000

원본 파일 이름: survey_2015_xxx.xyz
새 파일 이름: survey_2015_xxx_s.xyz

답변1

head음수 오프셋을 지원하는 경우 :

for file in *.xyz; do
  if [ "$(tail -n 1 < "$file")" = END ]; then
    head -n -1 < "$file" > "${file%.xyz}_s.xyz"
  fi
done

(그렇지 않은 경우 head -n -1로 대체하십시오 sed '$d').

다음을 통해 효율성을 향상할 수 있습니다 ksh93.

for file in *.xyz; do
  if IFS= read -r last4 < "$file" <#((EOF-4)) <#((here=CUR)) &&
    [ "$last4" = END ]; then
    command /opt/ast/bin/head -c "$here" < "$file" > "${file/%.xyz/_s\0}"
  fi
done

내장된 명령만 사용하기 때문입니다.

파일 시스템이 참조 링크 복사본을 지원하는 경우(즉, 수정될 때까지 데이터가 반복되지 않는 파일을 복사하여 시간과 디스크 공간을 절약하는 경우) ksh93GNU를 계속 cp사용할 수 있습니다.

for file in *.xyz; do
  if IFS= read -r last4 < "$file" <#((EOF-4)) &&
    [ "$last4" = END ]; then
    newfile=${file/%.xyz/_s\0}
    cp --reflink=auto -- "$file" "$newfile" &&
      : 1<>; "$newfile" >#((EOF-4))
  fi
done

즉, 우리는 reflink의 복사본을 만들고 끝에서 4바이트를 자릅니다.

답변2

또 다른 ed옵션은 단 한 번만 살기 때문에 다음과 같습니다.

for f in *.xyz; do
    printf '%s\n' ';g/END/d\' "w ${f%.xyz}_s.xyz" q | ed -s "$f"
done

파일 이름에 대한 참고 사항:

  • 파일 이름은 로 시작하면 안 됩니다 !. 그렇지 않으면 ed버퍼를 명령에 파이프하려고 시도합니다.
  • ed공백 문자는 명령을 경로 이름 인수와 구분하는 데 사용되므로 파일 w이름의 선행 공백은 유지되지 않습니다.
  • 줄바꿈이 포함된 파일 이름은 문제를 야기합니다. ed줄바꿈은 명령을 구분하는 데 사용되기 때문입니다.

정상적인 세상에서는 이러한 제한 사항 중 어느 것도 중요하지 않습니다. 잘……

답변3

그냥 다른 솔루션을 사용하세요sed

for file in *.xyz
do
    if [ "$(sed -e '$!d' $file)" = END ]
    then
        sed -e '$d' $file > $file_s.xyz
    fi
done

관련 정보