파일을 더 효율적으로 여러 조각으로 자르는 방법은 무엇입니까?

파일을 더 효율적으로 여러 조각으로 자르는 방법은 무엇입니까?

10MB 크기의 텍스트 파일이 있고 foo.txt100,000줄이 있다고 가정합니다. 이제 foo.txt창 크기 10을 사용하여 창별로 창을 처리하고 싶습니다 .

내 현재 스크립트는 다음과 같습니다.

for ((i=0;i<$lines;i=i+$step))
do    
    head -$((i+step)) $1 | tail -$step > tmp1
    head -$((i+step)) $2 | tail -$step > tmp2
    setstr=$setstr' '`./accuracy.sh tmp1 tmp2`
done
echo $setstr | awk '{for (i=1;i<=NF;i++) sum+=$i; }END{print sum/NF}'

하지만 천천히 실행됩니다. 이를 수행하는 더 간단하고 효율적인 방법이 있습니까?

답변1

다음을 사용하여 그렇게 할 수 있습니다 split.

사용 방법의 예는 다음과 같습니다.

split -l 10 input_file output_file_prefix_

옵션 -l은 다음을 의미합니다.--lines=

그리고 이것은 input_file각각 10줄씩 다음 파일로 분할됩니다.

output_file_prefix_aa
output_file_prefix_ab
output_file_prefix_ac
...

등등.

을 사용할 수 있는 다른 방법은 다음을 split참조하세요 .man split여기

답변2

코드 조각보다는 궁극적인 목표에 대해 좀 더 자세한 내용을 갖는 것이 유용할 것입니다. 특히 Accuracy.sh를 제어할 수 있나요?

어쨌든 bash를 계속 사용하고 싶다면 그렇게 할 수 있습니다.

for ((i=0;i<$lines;i+=$step))
do
  let end=i+10
  sed -n $i,${end}p $1 >tmp1
  sed -n $i,${end}p $2 >tmp2
  ...
done

답변3

이것이 StackOverflow에서 마이그레이션된 이유를 잘 모르겠습니다. 동안 split수퍼유저-스타일 답변, 질문은 프로그래밍에 관한 것이었습니다. 예를 들어, 다음은 에서 찾고 있는 것을 구현하는 답변입니다 awk.

의 정말 편리한 측면 중 하나 awk는 파이프를 처리하는 방식입니다.

#!/usr/bin/awk -f

BEGIN {
  cmd="/path/to/handler"
}

{
  print | cmd
}

NR % 10 == 0 {
  close(cmd)
}

cmd닫히면 다시 열리고 10번째 줄마다 닫혀서 다음 출력 줄에서 다시 열립니다 .

handler그 효과는 입력 10줄마다 실행되는 것입니다 . 파일 끝에서 awk가 종료되면 자동으로 닫히 handler므로 남은 줄로 실행됩니다 cmd.

엄밀히 말하면 명령을 저장하는 것과 같은 변수를 사용할 필요는 없지만 cmd명령을 조정하는 것이 더 간단해집니다. 그렇지 않으면 close().

답변4

이 솔루션은 임시 파일을 사용하지 않습니다. 10개의 라인을 보유할 수 있는 버퍼 배열에 모든 라인을 저장하는 것입니다. 줄 번호를 10으로 나눌 때마다 버퍼의 모든 줄을 인쇄합니다.

명백한 함정은 입력 파일(#줄)이 10으로 나누어지지 않을 때입니다. 해결책은 END{} 절을 확인하는 것입니다. 다음과 같은 것 :

$ 에코 {1..33} | tr \ \\n |\
    awk '{lines=NR} END{ if (lines%10!=0) { "남은 줄" 인쇄} }'
남은 줄

# STEP1 모듈로를 사용하여 10분의 1마다 무언가를 수행합니다.
$ echo {1..200} |tr \ \\n |\
    awk '{a[NR%10]=$0; if (NR%10==0) {print "ten"} }' | 고양이 -n
     1 10
     2 10
     3 10
     4 10
     5 10
     6 10
     7 10
     8 10
     9시 10분
    10 10
    11 10
    12 10
    13 10
    14 10
    15 10
    16 10
    17 10
    18 10
    19 10
    20 10

# STEP 2 모든 라인에 뭔가를 하세요
$ 에코 {1..10} | TR \ \\n | awk '{ b+=$0} END {인쇄 b}'
55

# 모아서
$ 고양이 Every10.awk
{
        a[NR%10]=$0;
        만약 (NR%10==0) {
                (나는 a에서) {
                        printf "%s+", a[i]
                        b+=a[i];
                }
                "0="을 인쇄하세요. b;
                b=0
        }
}
$ 에코 {1..200} | TR \ \\n | awk -f Every10.awk | 열 -s= -t
4+5+6+7+8+9+10+1+2+3+0 55
14+15+16+17+18+19+20+11+12+13+0 155
24+25+26+27+28+29+30+21+22+23+0 255
34+35+36+37+38+39+40+31+32+33+0 355
44+45+46+47+48+49+50+41+42+43+0 455
54+55+56+57+58+59+60+51+52+53+0 555
64+65+66+67+68+69+70+61+62+63+0 655
74+75+76+77+78+79+80+71+72+73+0 755
84+85+86+87+88+89+90+81+82+83+0 855
94+95+96+97+98+99+100+91+92+93+0 955
104+105+106+107+108+109+110+101+102+103+0 1055
114+115+116+117+118+119+120+111+112+113+0 1155
124+125+126+127+128+129+130+121+122+123+0 1255
134+135+136+137+138+139+140+131+132+133+0 1355
144+145+146+147+148+149+150+141+142+143+0 1455
154+155+156+157+158+159+160+151+152+153+0 1555
164+165+166+167+168+169+170+161+162+163+0 1655
174+175+176+177+178+179+180+171+172+173+0 1755
184+185+186+187+188+189+190+181+182+183+0 1855
194+195+196+197+198+199+200+191+192+193+0 1955

여기서 아이디어는 10줄의 awk 인쇄 블록을 사용하여 이를 처리하거나, 작업이 간단한 산술 또는 문자열 작업인 경우 awk로 직접 처리하는 것입니다.

관련 정보