2017-01-03 1 views
1

큰 (~ 870,000,000 줄) 텍스트 파일에서 특정 그룹의 행을 가져 오려고합니다. 예를 들어, 50 줄의 파일에서 3-6, 18-27, 39-45 줄을 원할 수 있습니다. 검색 스택 오버플로에서 큰 텍스트 파일에서 행 그룹 읽기

는, 내가 bash는 명령 것으로 나타났습니다 :

tail -n+NUMstart file |head -nNUMend 

한 줄 또는 NUMstart에서 시작 NUMend에가는 라인의 그룹을 얻을 수있는 가장 빠른 방법입니다. 그러나 여러 줄의 줄을 읽을 때 이것은 비효율적 인 것처럼 보입니다. 일반적으로이 기술은별로 중요하지 않지만이 파일은 커다란 차이를 만듭니다.

각 행 그룹에 대해 위의 명령을 사용하는 것보다 더 좋은 방법이 있습니까? 나는 그 대답이 bash 명령 일 가능성이 가장 높지만 실제로 일을 잘 수행 할 수있는 언어/도구에 대해 열려 있다고 가정하고 있습니다.

답변

3

선 3-6, 18-27을 보여주고 39-45 :

귀하의 경우에는

sed -n "3,6p;18,27p;39,45p" file 

또한에서 나오지 공급하는 것이 가능하다 파일. 파일 foobar

내용 :

 
3,6p 
18,27p 
39,45p 

사용법 : 구조에

sed -n -f foobar file 
+0

'awk'보다 훨씬 빠르다면 궁금합니다. – codeforester

+1

이것은 전체 파일을 스캔 할 것이고, 마지막 라인 다음에 끝낼 때'awk'보다 빠를 수 없다. – karakfa

+2

마지막 명령으로'45q'을 추가하면이를 수정합니다. –

0

다른 범위에 대한 tail -n XX file | head -n YY의 문제점은 여러 번 실행하므로 비효율적입니다. 그렇지 않은 경우 benchmarks은 최상의 솔루션이라고 제안합니다. 귀하의 경우에는

awk '(NR>=start1 && NR<=end1) || (NR>=start2 && NR<=end2) || ...' file 

:이 특정 사건에 대한

, 당신은 awk 사용할 수 있습니다, 당신 그룹 범위 및하자 awk 인쇄 해당 라인입니다

awk '(NR>=3 && NR<=6) || (NR>=18 && NR<=27) || (NR>=39 && NR<=45)' file 

을 때 파일을 한 번 반복하면됩니다. 마지막으로 흥미로운 행을 읽었을 때 처리가 완료되도록 최종 NR==endX {exit} (endX이 마지막 범위의 종결 항목 임)을 추가하는 것도 유용 할 수 있습니다. 나오지와

awk '(NR>=3 && NR<=6) || (NR>=18 && NR<=27) || (NR>=39 && NR<=45); NR==45 {exit}' file 
1

awk!

awk -v lines='3-6,18-27,39-45' ' 
     BEGIN {n=split(lines,a,","); 
       for(i=1;i<=n;i++) 
       {split(a[i],t,"-"); 
       rs[++c]=t[1]; re[c]=t[2]}} 

      {for(i=s;i<=c;i++) 
       if(NR>=rs[i] && NR<=re[i]) {print; next} 
       else if(NR>re[i]) s++; 
       if(s>c) exit}' file 

은 마지막 인쇄 된 줄 다음에 초기 종료를 제공합니다. 오류를 점검하지 않으면 범위가 증가하는 순서로 제공되어야합니다.

+0

좋은 접근 방식. 그러나, 나는 범위 먹이가 여기에서 특별한 문제라고 생각하지 않는다, 그래서 BEGIN 블록은 (나에게) 어떻게 든 관련성이 없다. – fedorqui