पाठ फ़ाइल को शब्दों की निश्चित संख्या के साथ लाइनों में विभाजित करें


11

संबंधित, लेकिन कोई संतोषजनक जवाब नहीं: मैं एक बड़ी पाठ फ़ाइल को 500 शब्दों या उसके अंशों में कैसे विभाजित कर सकता हूं?

मैं एक टेक्स्ट फ़ाइल ( http://mattmahoney.net/dc/text8.zip ) को> 10 ^ 7 शब्दों के साथ एक पंक्ति में लेने की कोशिश कर रहा हूं , और इसे प्रत्येक एन शब्दों के साथ लाइनों में विभाजित करता हूं । मेरा वर्तमान दृष्टिकोण काम करता है, लेकिन काफी धीमा और बदसूरत है (शेल स्क्रिप्ट का उपयोग करके):

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

मैं इसे कैसे तेज या अधिक कॉम्पैक्ट बना सकता हूं, इस पर कोई सुझाव?


यदि आप इसे तेजी से चाहते हैं, तो आपको कुछ और उपयोग करने की आवश्यकता है फिर स्क्रिप्ट को बैश करें। मैं कुछ सी की सिफारिश करूंगा। यह कुछ पंक्तियों में फिट हो सकता है।
जकूजी

जवाबों:


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जो अधिकतम तर्कों को परिभाषित करता है। बस या जो भी सीमा आप चाहते हैं बदलने के 1000लिए 500

मैंने 10 ^ 7 शब्दों के साथ एक परीक्षण फ़ाइल बनाई:

$ wc -w file
10000000 file

यहाँ समय आँकड़े हैं:

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

यह मेरे द्वारा स्वीकार किए गए उत्तर की तुलना में थोड़ा धीमा है (मेरी फाइल पर 21s बनाम 12)
Cory Schillaci

1
बहुत बढ़िया विचार +1, हालांकि सावधान रहना xargsकी बोली-अलग करना व्यवहार
इरुवर

यह जितना 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 solution को सिर्फ 5 सेकंड से अधिक समय लगा।


5

वास्तव में उपयुक्त नहीं है जब Nशब्दों का umber एक बड़ी संख्या है, लेकिन अगर यह एक छोटी संख्या है (और आदर्श रूप से, आपकी एक-पंक्ति फ़ाइल में कोई अग्रणी / अनुगामी स्थान नहीं है) तो यह बहुत तेज़ होना चाहिए (जैसे प्रति पंक्ति 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आदि के माध्यम से ... और फिर भी, वहाँ एक sytem विशिष्ट अधिकतम संख्या में तर्क हैं (मैं सभी स्वादों से परिचित नहीं हूं pasteलेकिन मुझे लगता है कि कुछ कार्यान्वयन के साथ args / इनपुट फ़ाइलों और / या आउटपुट लाइन की लंबाई के रूप में सीमाएं हैं ...)
don_crissti

3

एक ही सीड कमांड को यह निर्दिष्ट करके सरल किया जा सकता है कि आप कितने शब्द-स्थान पैटर्न से मेल खाना चाहते हैं। मेरे पास इसका परीक्षण करने के लिए कोई बड़ी स्ट्रिंग फ़ाइलें नहीं थीं, लेकिन आपकी मूल स्क्रिप्ट में लूप के बिना यह उतना तेज़ चलना चाहिए जितना आपका प्रोसेसर डेटा को स्ट्रीम कर सके। जोड़ा गया लाभ, यह मल्टी-लाइन फ़ाइलों पर समान रूप से अच्छी तरह से काम करेगा।

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

कोरुटिल्स 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

[ग्लेन का पर्ल समाधान अभी भी थोड़ा तेज है, इस मशीन पर ~ 1.8 s]।


1

जाने में मैं इसे इस तरह की कोशिश करेंगे

//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])
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.