고정 된 수의 단어가있는 줄로 텍스트 파일 나누기


11

관련이 있지만 만족스러운 답변은 없습니다 . 큰 텍스트 파일을 500 단어 정도의 청크로 나눌 수 있습니까?

한 줄에 10 ^ 7 개 이상의 단어 가있는 텍스트 파일 ( http://mattmahoney.net/dc/text8.zip ) 을 가져 와서 N 단어가있는 줄로 나눕니다. 내 현재 접근 방식은 작동하지만 상당히 느리고 추악합니다 (쉘 스크립트 사용).

i=0
for word in $(sed -e 's/\s\+/\n/g' input.txt)
do
    echo -n "${word} " > output.txt
    let "i=i+1"

    if [ "$i" -eq "1000" ]
    then
        echo > output.txt
        let "i=0"
    fi
done

더 빠르고 컴팩트하게 만드는 방법에 대한 팁이 있습니까?


더 빨리 원한다면 다른 것을 사용해야하고 스크립트를 bash해야합니다. 나는 약간의 C를 추천합니다. 그것은 몇 줄에 맞을 수 있습니다.
Jakuje

답변:


5

단어 정의가 공백으로 구분 된 일련의 공백이 아닌 문자라고 가정하면 다음은 한 awk줄 파일에 대한 솔루션입니다

awk '{for (i=1; i<=NF; ++i)printf "%s%s", $i, i % 500? " ": "\n"}i % 500{print ""}' file

11

사용 xargs(17 초) :

xargs -n1000 <file >output

최대 인수 수를 정의 하는 -n플래그를 사용합니다 xargs. 그냥 변경 1000500또는 무엇이든 당신이 원하는 제한합니다.

10 ^ 7 단어로 테스트 파일을 만들었습니다.

$ wc -w file
10000000 file

시간 통계는 다음과 같습니다.

$ time xargs -n1000 <file >output
real    0m16.677s
user    0m1.084s
sys     0m0.744s

이것은 내가 (내 파일에 12S 대 21S) 허용 대답보다 약간 느린
코리 Schillaci을

1
좋은 생각 하나, 그러나 조심 xargss '를 인용-제거 행동
iruvar

n아시다시피 느려질 수록 느려집니다. 함께 -n10내가 기다리고의 약 8 분 후 취소 ...
don_crissti

7

펄은 이것에 상당히 놀랍게 보인다 :

10,000,000 개의 공백으로 구분 된 단어가있는 파일 만들기

for ((i=1; i<=10000000; i++)); do printf "%s " $RANDOM ; done > one.line

이제 펄은 1,000 단어마다 줄 바꿈을 추가합니다

time perl -pe '
    s{ 
        (?:\S+\s+){999} \S+   # 1000 words
        \K                    # then reset start of match
        \s+                   # and the next bit of whitespace
    }
    {\n}gx                    # replace whitespace with newline
' one.line > many.line

타이밍

real    0m1.074s
user    0m0.996s
sys     0m0.076s

결과 확인

$ wc one.line many.line
        0  10000000  56608931 one.line
    10000  10000000  56608931 many.line
    10000  20000000 113217862 total

승인 된 awk 솔루션은 입력 파일에서 5 초 이상 걸렸습니다.


5

N엄청나게 많은 단어가 큰 숫자 일 때는 적합하지 않지만 작은 숫자 일 경우 (한 줄의 파일에 선행 / 트레일 공백이없는 경우)이 속도는 매우 빠릅니다 (예 : 한 줄에 5 단어).

tr -s '[[:blank:]]' '\n' <input.txt | paste -d' ' - - - - - >output.txt

1
이것은 많은 수의 경우에도 완벽하게 훌륭하며 맹목적으로 빠릅니다. paste즉시 문자열을 생성하십시오 . 예를 들면 :tr -s '[[:blank:]]' '\n' < text8 | paste -d' ' $(perl -le 'print "- " x 1000')
terdon

@terdon - 사실, 많은 수의 하나는 당신이 한 또는를 통해 같이 명령 인수 예 구축해야하지만 set등등 ... 심지어 한 후, 인수의 시스템이 재부 특정 최대 수는 내가 모든 맛에 익숙하지 않다 (거기에 paste있지만, 전 사실에 관해서는 한계가 있습니까 일부 구현으로 생각 인수 / 입력 파일 및 / 또는 출력 라인 길이 ...)의.
don_crissti

3

일치시킬 단어 공간 패턴 수를 지정하여 동일한 sed 명령을 단순화 할 수 있습니다. 테스트 할 큰 문자열 파일이 없었지만 원래 스크립트에 루프가 없으면 프로세서가 데이터를 스트리밍 할 수있는 한 빨리 실행되어야합니다. 추가 된 이점은 여러 줄 파일에서도 동일하게 작동합니다.

n=500; sed -r "s/((\w+\s){$n})/\1\n/g" <input.txt >output.txt

3

fmt(1)"특정 단어 수"로 엄격하게 작동하지는 않지만 훌륭한 명령은 긴 행을 특정 목표 (또는 최대) 너비로 상당히 빠르게 줄 바꿈 할 수 있습니다.

perl -e 'for (1..100) { print "a"x int 3+rand(7), " " }' | fmt

또는 현대 펄을 사용하여 특정 단어 수 (10)를 지정하고 단일 공간을 단어 경계로 가정합니다.

... | perl -ple 's/(.*? ){10}\K/\n/g'

2

coreutils pr명령은 또 다른 후보입니다. 유일한 주름은 출력 너비를 수용 할 수 있도록 페이지 너비를 충분히 크게해야한다는 것입니다.

@Glenn_Jackman의 10,000,000 단어 생성기를 사용하여 만든 파일을 사용하여

$ time tr '[[:blank:]]' '\n' < one.line | pr -s' ' -W 1000000 -JaT -1000 > many.line

real    0m2.113s
user    0m2.086s
sys 0m0.411s

카운트가 다음과 같이 확인되는 곳

$ wc one.line multi.line 
        0  10000000  56608795 one.line
    10000  10000000  56608795 many.line
    10000  20000000 113217590 total

[Glenn의 perl 솔루션은 여전히이 머신에서 ~ 1.8s로 조금 더 빠릅니다.]


1

Go에서 나는 이것을 이렇게 시도 할 것입니다

//wordsplit.go

//$ go run wordsplit.go bigtext.txt

package main


import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "strings"
)


func main() {
    myfile, err := os.Open(os.Args[0])
    if err != nil {
        log.Fatal(err)
    }
    defer myfile.Close()
    data, err := ioutil.ReadAll()
    if err != nil {
        log.Fatal(err)
    }
    words := strings.Split(data, " ")
    newfile, err := os.Create("output.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer newfile.Close()
    for i := 0; i < len(words)-10; i+10 {
        newfile.WriteString(words[i:i+10])
    }
    newfile.WriteString(words[-(len(words)%10):])
    fmt.Printf("Formatted %s into 10 word lines in output.txt", os.Args[0])
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.