다음과 같은 세부 정보가 포함된 세 개의 큰 파일이 있는 장면이 있습니다 Test.txt
.Test1.txt
Test2.txt
H|||||||||||||||||||||||
D||||||||||||||||||||||||
D|||||||||||||||||||||||
H|||||||||||||||||||||
D||||||||||||||||||||||||
D||||||||||||||||||||||||
T||||||||||||||||||||||||
D라인을 제외한 모든 항목을 삭제해야 합니다. 내 파일 세 개 모두에서 다음과 같이 보일 것입니다. (10GB 이상)
D||||||||||||||||||||||||
D|||||||||||||||||||||||
D||||||||||||||||||||||||
D||||||||||||||||||||||||
Test.txt
따라서 , Test2.txt
, 및 에서 D 줄만 유지한 후 Test3.txt
새 파일로 병합해야 합니다.
나는 sed를 사용하여 위의 작업을 수행했습니다.
sed '/^\('D'\)|/!d' $Filename.txt >> $NewFilename.txt
하지만 파일이 크기 때문에 시간이 오래 걸립니다.
이를 효율적으로 수행하기 위해 사용할 수 있는 다른 명령이 있습니까?
답변1
cat Test.txt Test2.txt Test3.txt | LC_ALL=C grep '^D' > newfile.txt
또는:
for file in Test.txt Test2.txt Test3.txt; do
LC_ALL=C grep '^D' < "$file"
done > newfile.txt
또는 grep
선호하는 GNU가 grep
해당 -h
옵션을 지원하는 경우(파일 이름 인쇄를 피하기 위해):
LC_ALL=C grep -h '^D' Test.txt Test2.txt Test3.txt > newfile.txt
이를 사용하면 UTF-8 데이터 구문 분석을 피할 LC_ALL=C
수 있습니다 . grep
를 사용하면 ^D
각 grep
줄의 첫 번째 문자만 표시됩니다. grep
, 특히 grep
GNU는 일반적으로 sed
.
답변2
이는 CPU 바인딩이 아닌 I/O 바인딩 작업일 가능성이 높으므로 다음과 같은 정규식 엔진을 사용하지 않더라도 다음과 같습니다.
grep -F 'D|' Test.txt Test2.txt Test3.txt
파일을 선으로 표시한 후 패턴을 검색해야 하기 때문에 시간이 오래 걸립니다.
이것이 일회성이고 인코딩에 신경 쓰지 않는다면 mmap(3)
전체 파일을 메모리에 넣고 다음을 사용할 수 있습니다 memmem(3)
.
char *p;
if ((p = memmem(file, size, "\nD|", 3)) != NULL) {
/* massage the line, i.e. find the next '\n'
* and print the region between p+1 and the
* next '\n' */
}
어디에 file
매핑된 버퍼에 대한 포인터이고 size
파일 크기입니다. (도움이 된다면 자세히 설명해 드리겠습니다.)
이 접근 방식은 여전히 시간이 좀 걸리지만(문제가 I/O 바인딩되어 있기 때문에) 최소한 파일을 행으로 표시하는 시간을 절약할 수 있습니다.