bash 스크립트를 사용하여 거대한 텍스트 파일에서 첫 번째 줄을 반복해서 제거해야합니다.
지금은 사용하고 sed -i -e "1d" $FILE
있지만 삭제하는 데 약 1 분이 걸립니다.
이것을 달성하는 더 효율적인 방법이 있습니까?
bash 스크립트를 사용하여 거대한 텍스트 파일에서 첫 번째 줄을 반복해서 제거해야합니다.
지금은 사용하고 sed -i -e "1d" $FILE
있지만 삭제하는 데 약 1 분이 걸립니다.
이것을 달성하는 더 효율적인 방법이 있습니까?
답변:
꼬리를 보십시오 :
tail -n +2 "$FILE"
-n x
: 마지막 x
줄만 인쇄하십시오 . tail -n 5
입력의 마지막 5 줄을 줄 것입니다. +
반전의 부호 종류의 인수 및 메이크업 tail
인쇄 아무것도하지만 첫 번째 x-1
라인. tail -n +1
전체 파일을 인쇄하고tail -n +2
첫 번째 줄을 제외한 모든 것을 .
GNU tail
는보다 훨씬 빠릅니다 sed
. tail
BSD에서도 사용할 수 있으며 -n +2
플래그는 두 도구에서 일관됩니다. 자세한 내용은 FreeBSD 또는 OS X 매뉴얼 페이지를 확인하십시오 .
그러나 BSD 버전은보다 느릴 수 있습니다 sed
. 그들이 어떻게 관리했는지 궁금합니다. 스크립트를 해석하고 정규 표현식을 적용하는 등의 복잡한 작업을 수행하는 tail
동안 파일을 한 줄씩 읽어야합니다 sed
.
참고 : 사용하고 싶을 수도 있습니다
# THIS WILL GIVE YOU AN EMPTY FILE!
tail -n +2 "$FILE" > "$FILE"
그러나 이것은 당신에게 빈 파일을 줄 것 입니다. 쉘이 재 호출 >
하기 전에 재 지정 ( )이 발생하기 때문 tail
입니다.
$FILE
tail
tail
프로세스의 표준 출력 을$FILE
tail
지금 비어있는에서 읽습니다 $FILE
파일 내부의 첫 번째 줄을 제거하려면 다음을 사용해야합니다.
tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
은 &&
문제가있을 때 파일이 덮어하지 않도록 할 것입니다.
-r
옵션 과 함께 BSD 'tail'을 사용할 때 일반적인 버퍼의 기본값은 32k 입니다. 시스템 어딘가에 버퍼 설정이 있습니까? 아니면 -n
32 비트 부호있는 숫자입니까?
tail
모든 파일 크기에서 작동합니다.
-n N means output the last N lines, instead of the last 10; or use +N to output lines starting with the Nth
'>'연산자를 사용하지 않고 -i를 사용하여 파일을 업데이트 할 수 있습니다. 다음 명령은 파일에서 첫 번째 줄을 삭제하고 파일에 저장합니다.
sed -i '1d' filename
unterminated transform source string
sed -i '1,2d' filename
tail -n +2
입니다. 왜 최고의 답변이 아닌지 잘 모르겠습니다.
아니, 그것은 당신이 얻을만큼 효율적입니다. 작업을 조금 더 빠르게 할 수있는 C 프로그램을 작성할 수는 있지만 (시작 시간이 적고 인수를 처리하는 경우) 파일이 커질 때 sed와 동일한 속도로 향할 수 있습니다 (분이 걸리면 크기가 크다고 가정합니다) ).
그러나 귀하의 질문에는 솔루션을 미리 제안한다는 점에서 다른 많은 사람들과 동일한 문제가 있습니다. 당신이 세부에서 우리에게 얘기를한다면 무엇을 당신이보다는 일을하려고하고 어떻게 , 우리는 더 나은 옵션을 제안 할 수 있습니다.
예를 들어, 이것이 다른 프로그램 B가 처리하는 파일 A 인 경우 한 솔루션은 첫 번째 행을 제거하지 않고 프로그램 B를 수정하여 다르게 처리하는 것입니다.
모든 프로그램이이 파일 A에 추가되고 프로그램 B는 현재 첫 번째 행을 읽고 처리하기 전에이를 읽습니다.
프로그램 B를 다시 엔지니어링하여 첫 번째 줄을 삭제하려고 시도하지 않았지만 파일 A에 대한 영구적 인 (아마도 파일 기반) 오프셋을 유지하여 다음에 실행될 때 해당 오프셋을 찾고 프로세스를 찾을 수 있습니다. 거기에 선을 긋고 오프셋을 업데이트하십시오.
그런 다음 조용한 시간 (자정?)에서 파일 A의 특수 처리를 수행하여 현재 처리 된 모든 행을 삭제하고 오프셋을 다시 0으로 설정할 수 있습니다.
프로그램이 파일을 열고 다시 쓰는 것이 아니라 파일을 열고 찾는 것이 더 빠를 것입니다. 이 토론은 물론 프로그램 B를 제어한다고 가정합니다. 그 경우인지 모르겠지만 추가 정보를 제공하면 다른 가능한 해결책이있을 수 있습니다.
awk FNR-1 *.csv
아마도 더 빠를 것입니다.
Pax가 말했듯이 아마도 이것보다 더 빠를 수는 없습니다. 그 이유는 파일 시작 부분에서 잘림을 지원하는 파일 시스템이 거의 없기 때문에 파일 크기가 O ( n
) 작업 이 될 것 n
입니다. 훨씬 더 빨리 할 수있는 일은 동일한 바이트 수 (공백 또는 주석이있을 수 있음)로 첫 번째 줄을 덮어 쓰는 것입니다. 실제로 수행하려는 작업에 따라 작동 할 수 있습니다 (무엇입니까?).
이 sponge
유틸리티 는 임시 파일을 저글링 할 필요가 없습니다.
tail -n +2 "$FILE" | sponge "$FILE"
sponge
실제로 허용 된 솔루션 ( tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
) 보다 훨씬 더 깨끗하고 강력합니다.
sponge
전체 파일을 메모리에 버퍼링합니까? 수백 GB이면 작동하지 않습니다.
sponge
있는 한 / tmp 파일을 중간 단계로 사용하여 나중에 원본을 대체하는 데 사용 되므로 파일 시스템에 흡수됩니다 .
이 곳에서 파일을 수정하려면, 당신은 항상 원래 사용할 수있는 ed
대신의 의의 treaming 후계자를 sed
:
ed "$FILE" <<<$'1d\nwq\n'
ed
도 훨씬 덜 그래픽 워크 스테이션 전체 화면 단자가되기 전에 명령은 원래 UNIX 텍스트 편집기이었다. ex
편집기, 최고의 입력은 콜론 프롬프트에서 때 사용중인로 알려진 vi
,입니다 전직 의 경향 버전의 ed
동일한 명령 작업의 많은이. ed
대화식으로 사용하기위한 것이지만 ,이 솔루션이 수행하는 명령 문자열을 전송하여 배치 모드에서도 사용할 수 있습니다.
순서는 <<<$'1d\nwq\n'
여기 - 스트링 (위한 배시의 지원을 활용 <<<
() 및 POSIX 지수 $'
... '
받는 이송 입력) ed
: 두 개의 라인으로 이루어진 명령 1d
, 개발 eletes가 라인 1을 다음과 wq
어느 w 밖으로 의식 파일 뒷면 디스크는 q는 편집 세션을 UITS.
vim을 사용하여이를 수행 할 수 있습니다.
vim -u NONE +'1d' +'wq!' /tmp/test.txt
vim은 프로세스 할 때 전체 파일을 읽지 않기 때문에 더 빠릅니다.
+wq!
쉘이 bash라면 인용해야 할 수도 있습니다. 아마도 !
단어의 시작 부분이 아니기 때문에 아마도 인용하지 않는 것이 좋을 것입니다. (그리고 불필요하게 인용하지 않음으로써 초 고효율을 원한다면 인용 부호가 필요하지 않습니다 1d
.)
삭제 속도를 높일 수없는 것처럼 들리므로 다음과 같이 파일을 일괄 처리하는 것이 좋습니다.
While file1 not empty
file2 = head -n1000 file1
process file2
sed -i -e "1000d" file1
end
이것의 단점은 프로그램이 중간에 죽거나 (혹은 거기에 나쁜 sql이있어 "프로세스"부분이 죽거나 잠기는 경우) 줄을 건너 뛰거나 두 번 처리한다는 것입니다. .
(file1은 SQL 코드 줄을 포함합니다)
N-1 행에 tail을 사용하여 파일로 지정하고 이전 파일을 제거한 다음 새 파일의 이름을 이전 이름으로 바꾸겠습니까?
프로그래밍 방식 으로이 작업을 수행하는 경우 파일을 읽고 각 줄을 읽은 후 파일 오프셋을 기억하므로 해당 위치로 돌아가서 줄이 하나 적은 파일을 읽을 수 있습니다.