거대한 텍스트 파일에서 'head'또는 'tail'사용-19GB


15

매우 큰 텍스트 파일을 보는 데 문제가 있습니다. 약 19GB의이 파일은 전통적인 방법으로는보기에는 너무 큽니다.

나는 두 가지 명령을 여러 가지 방법으로 (중간 조각으로 만들기 위해) 함께 파이프로 시도 head 1하고 tail 1( head -n 1tail -n 1) 운없이. Ubuntu 9.10을 실행하는 Linux 시스템에서이 파일을 처리 할 수 ​​없습니다.

이 파일을 어떻게 처리합니까? 나의 궁극적 인 목표는 45000000 라인과 45000100 라인에서 연마하는 것입니다.


줄을 읽고 제출해야 할 줄을 인쇄하기 위해 빠른 Python 스크립트를 작성하려고 생각하지만 시간이 오래 걸리는 것을 상상할 수 있습니다 ...
nicorellius

모든 선이 같은 길이입니까?
Paul

@Paul-불행히도, 그들은 같은 길이가 아닙니다.
nicorellius

당신이 시도 할 수 split와 작업에 큰 파일을 쉽게 할 수 있습니다.
iglvzx 2019

1
확인. 큰 파일을 처리하는 데 시간이 걸리므로 아래 답변이 도움이 될 것입니다. 찾고자하는 부분 만 추출하고 대략적인 위치를 추정 할 수 dd있다면 이후의 비트를 얻는 데 사용할 수 있습니다 . 예를 들어 dd if=bigfile of=extractfile bs=1M skip=10240 count=510GB 지점부터 시작하여 파일에서 5MB를 추출합니다.
Paul

답변:


11

을 사용해야합니다 sed.

sed -n -e 45000000,45000100p -e 45000101q bigfile > savedlines

sed45000000-45000100 줄을 인쇄하고 45000101 줄을 끝내 라고 지시 합니다.


1
여전히 머리처럼 느리다. -45000000,45000100p bigfile | tail -100> savedlines
Dmitry Polushkin

tail+|head좋은 10-15 % 빠릅니다.
Erich

4

단일 필드가있는 단일 테이블로 MySQL 데이터베이스를 작성하십시오. 그런 다음 파일을 데이터베이스로 가져 오십시오. 이를 통해 특정 라인을 쉽게 찾을 수 있습니다.

나는 아무것도 빨리 될 수 있다고 생각 (만약하지 않습니다 headtail이미 실패). 결국 줄을 찾으려는 응용 프로그램 nn개행 을 찾을 때까지 전체 파일을 찾아야합니다 . 일종의 조회 (파일에 대한 행 인덱스에서 바이트 오프셋까지)가 없으면 더 나은 성능을 얻을 수 없습니다.

MySQL 데이터베이스를 생성하고 데이터를 가져 오는 것이 얼마나 쉬운 지 감안할 때 이것이 실용적인 접근법이라고 생각합니다.

방법은 다음과 같습니다.

DROP DATABASE IF EXISTS helperDb;
CREATE DATABASE `helperDb`;
CREATE TABLE `helperDb`.`helperTable`( `lineIndex` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `lineContent` MEDIUMTEXT , PRIMARY KEY (`lineIndex`) );
LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable (lineContent);
SELECT lineContent FROM helperTable WHERE ( lineIndex > 45000000 AND lineIndex < 45000100 );

/tmp/my_large_file 읽고 싶은 파일입니다.

각 줄에 탭으로 구분 된 값을 가진 파일을 가져 오는 올바른 구문은 다음과 같습니다.

LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable FIELDS TERMINATED BY '\n' (lineContent);

이것의 또 다른 주요 장점은 나중에 다른 라인 세트를 추출하기로 결정한 경우 (물론 데이터베이스를 삭제하지 않는 한) 처리를 다시 몇 시간 기다릴 필요가 없다는 것입니다.


실제로 이것은 좋은 해결책입니다. sed아래 명령 으로 작동하도록하고 내 줄을 식별했습니다. 그러나 이제 데이터베이스 방법이 더 적합 할 수 있다는 후속 질문이 있습니다. 이제 파일에서 몇 백 줄을 삭제해야합니다.
nicorellius

나는 sed그렇게 할 수 있다고 확신 합니다. 물론 데이터베이스에 데이터가있는 경우 원하는 줄만 사용하여 새 파일을 내보내는 것이 쉽지 않습니다.
Der Hochstapler

다시 감사합니다. 나는 sed대답을 취했다. (그것은 더 즉각적인 즐거움을 주었기 때문에 ;-) 장래에 당신의 방법을 사용할 것이기 때문에 당신에게 투표권을 주었다. 감사합니다.
nicorellius

1
당신은 추가 시도해 볼 수도 FIELDS TERMINATED BY '\n'받는 LOAD DATA라인.
Der Hochstapler

1
죄송합니다. 코드에 실수가있었습니다. 또한 귀하의 경우에 맞는 구문을 추가했습니다 (이번 테스트).
Der Hochstapler

1

큰 파일에 대한 두 가지 좋은 오래된 도구는 joinsplit. --lines=<number>파일을 특정 크기의 여러 파일로 자르는 옵션 과 함께 split을 사용할 수 있습니다 .

예를 들어 split --lines=45000000 huge_file.txt. 결과 부분은 xa, xb 등이됩니다. 그러면 원하는 선을 포함하는 head부분 xb 가 가능 합니다 . 파일을 하나의 큰 파일로 다시 '결합'할 수도 있습니다.


굉장히 고마워요 분할 명령을 잊어 버렸습니다
siliconrockstar

0

올바른 도구가 있지만 잘못 사용하고 있습니다. 이전 U & L에서 대답 했듯이 tail -n +X file | head -n Y( +)는 sedX에서 시작하는 Y 줄 보다 10-15 % 더 빠릅니다. 편리하게는와 exit같이 명시 적 으로 프로세스 를 수행하지 않아도됩니다 sed.

tail은 첫 번째 X-1 줄을 읽고 버리고 (그 주위에 방법은 없습니다) 다음 줄을 읽고 인쇄합니다. head는 요청 된 줄 수를 읽고 인쇄 한 다음 종료합니다. 헤드가 종료되면 tail은 SIGPIPE 신호를 수신하고 죽으므로 입력 파일에서 버퍼 크기에 해당하는 값 (일반적으로 몇 킬로바이트) 이상의 행을 읽지 못합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.