एक अलग फ़ाइल में प्रत्येक पंक्ति का आउटपुट भाग


14

मेरे पास इस तरह की एक फाइल है:

a   AGTACTTCCAGGAACGGTGCACTCTCC
b   ATGGATTTTTGGAGCAGGGAGATGGAATAGGAGCATGCTCCAT
c   ATATTAAATGGATTTTTGGAGCAGGGAGATGGAATAGGAGCATGCTCCATCCACTCCACAC
d   ATCAGTTTAATATCTGATACGTCCTCTATCCGAGGACAATATATTAAATGGA
e   TTTGGCTAAGATCAAGTGTAGTATCTGTTCTTATAAGTTTAATATCTGATATGTCCTCTATCTGA

मैं फाइल बनाना चाहता हूं a.seqजिसमें अनुक्रम हो AGTACTTCCAGGAACGGTGCACTCTCC। इसी प्रकार b.seqहोता है ATGGATTTTTGGAGCAGGGAGATGGAATAGGAGCATGCTCCAT। संक्षेप में, Column1 को विस्तार के साथ आउटपुट फ़ाइल नाम के रूप में इस्तेमाल किया जाना चाहिए .seqऔर फिर इसमें संबंधित कॉलम 2 अनुक्रम होना चाहिए। मैं एक पर्ल स्क्रिप्ट लिखकर ऐसा कर सकता हूं लेकिन कमांड लाइन पर कुछ भी मददगार होगा। जल्द ही सुनने की उम्मीद है।

जवाबों:


16

मेरी तस्वीर की प्रतिक्रिया होती, awkलेकिन अगर आप बहुत सारी लाइनों को संसाधित कर रहे हैं-और मैं लाखों लोगों के बारे में बात कर रहा हूं - तो आप संभवतः "वास्तविक" प्रोग्रामिंग भाषा पर स्विच करने से वास्तविक लाभ देखेंगे।

इसे ध्यान में रखते हुए (और awkपहले से ही एक उत्तर के रूप में लिया जा रहा है) मैंने विभिन्न भाषाओं में कुछ कार्यान्वयन लिखे और पीसीआई-ई एसएसडी पर उसी 10,000-लाइन डेटासेट पर उन्हें बेंचमार्क किया।

me* (C)                0m1.734s
me (C++)               0m1.991s
me (Python/Pypy)       0m2.390s
me (perl)              0m3.024s
Thor+Glenn (sed|sh)    0m3.353s
me (python)            0m3.359s
jasonwryan+Thor (awk)  0m3.779s
rush (while read)      0m6.011s
Thor (sed)             1m30.947s
me (parallel)          4m9.429s

एक नज़र में C सबसे अच्छा दिखता है लेकिन यह उस तेज़ को चलाने के लिए एक सुअर था। PyPy और सी ++ ज्यादा लिखने के लिए आसान कर रहे हैं और प्रदर्शन काफी अच्छी तरह से जब तक आप लाइनों के कई अरबों के बारे में बात कर रहे हैं। अगर ऐसा होता, तो RAM या SSD में यह सब करने के लिए अपग्रेड एक कोड सुधार से बेहतर निवेश हो सकता है।

जाहिर है कि मैंने इनसे गुजरने के समय में शायद सबसे कम विकल्प में कुछ सौ मिलियन रिकॉर्ड संसाधित किए हैं । यदि आप केवल awkलूप या बैश लिख सकते हैं , तो ऐसा करें और जीवन के साथ आगे बढ़ें। मैं स्पष्ट रूप से आज बहुत ज्यादा खाली समय था।

मैंने कुछ बहु-थ्रेडेड विकल्पों (C ++ और पायथन और GNU के साथ संकर parallel) का भी परीक्षण किया था, लेकिन इस तरह के एक सरल ऑपरेशन (स्ट्रिंग विभाजन, लेखन) के लिए किसी भी लाभ से पूरी तरह से धागे के ओवरहेड पूरी तरह से निकल जाते हैं।

पर्ल

awk( gawkयहाँ) ईमानदारी से इस तरह डेटा का परीक्षण करने के लिए कॉल का मेरा पहला बंदरगाह होगा, लेकिन आप पर्ल में काफी समान चीजें कर सकते हैं। समान सिंटैक्स लेकिन थोड़ा बेहतर लेखन हैंडल के साथ।

perl -ane 'open(my $fh, ">", $F[0].".seq"); print $fh $F[1]; close $fh;' infile

अजगर

मुझे पायथन पसंद है। यह मेरी दिन की नौकरी की भाषा है और यह एक अच्छी, ठोस और अविश्वसनीय रूप से पठनीय भाषा है। यहां तक ​​कि एक शुरुआत शायद यह अनुमान लगा सकती है कि यहां क्या हो रहा है।

with open("infile", "r") as f:
    for line in f:
        id, chunk = line.split()
        with open(id + ".seq", "w") as fw:
            fw.write(chunk)

आपको यह याद रखना होगा कि आपके वितरण का pythonबाइनरी केवल पायथन का कार्यान्वयन नहीं है। जब मैंने Pypy के माध्यम से इसी परीक्षण को चलाया, तो यह बिना किसी और तर्क अनुकूलन के C से तेज था । पायथन को "धीमी भाषा" के रूप में लिखने से पहले ध्यान रखें।

सी

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

मेरा मूल संस्करण C ++ और pypy की तुलना में धीमा था, लेकिन इसके बारे में ब्लॉगिंग के बाद मुझे जूलियन क्लोड से कुछ मदद मिली । यह संस्करण अब अपने सबसे तेज़ आईओ बफ़र्स के कारण सबसे तेज़ है। यह किसी भी चीज़ की तुलना में बहुत लंबा और अधिक शामिल है।

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>

#define BUFLEN (8 * 1024)

int main(void) {
    FILE *fp;
    FILE *fpout;

    char line[100];
    char *id;
    char *token;
    char *buf = malloc(BUFLEN);

    fp = fopen("infile", "r");

    setvbuf ( fp , buf , _IOLBF, BUFLEN );
    while (fgets(line, 100, fp) != NULL) {
        id = strtok(line, "\t");
        token = strtok(NULL, "\t");

        char *fnout = malloc(strlen(id)+5);
        fnout = strcat(fnout, id);
        fnout = strcat(fnout, ".seq");

        fpout = fopen(fnout, "w");
        setvbuf ( fpout , NULL , _IONBF , 0 );
        fprintf(fpout, "%s", token);
        fclose(fpout);
    }
    fclose(fp);

    return 0;
}

सी ++

अच्छा प्रदर्शन करता है और वास्तविक सी की तुलना में लिखना बहुत आसान है। आपके पास सभी प्रकार की चीजें हैं जो आपके हाथ को पकड़ती हैं (विशेषकर जब यह तार और इनपुट की बात आती है)। इसका मतलब है कि आप वास्तव में तर्क को सरल बना सकते हैं। strtokसी में एक हॉग है क्योंकि यह पूरे स्ट्रिंग को संसाधित करता है और फिर हमें वह सभी थकाऊ स्मृति आवंटन करने की आवश्यकता है। यह सिर्फ टैब को हिट करने तक लाइन के साथ बहता है और हम सेगमेंट को बाहर खींचते हैं जैसे हमें उनकी आवश्यकता होती है।

#include <fstream>
#include <string>
using namespace std;

int main(void) {
    ifstream in("infile");
    ofstream out;
    string line;

    while(getline(in, line)) {
        string::size_type tab = line.find('\t', 0);
        string filename = line.substr(0, tab) + ".seq";
        out.open(filename.c_str());
        out << line.substr(tab + 1);
        out.close();
    }

    in.close();
}

जीएनयू समानांतर

(नहीं संस्करण संस्करण)। यह एक अच्छा संक्षिप्त वाक्य-विन्यास है लेकिन OMGSLOW है। मैं इसे गलत उपयोग कर सकता हूं।

parallel --colsep '\t' echo {2} \> {1}.seq <infile

टेस्ट हार्नेस जनरेटर

यहां [ATGC] * 64 की 100000 लाइनों के लिए मेरा डेटा-जनरेटर है। यह तेज़ नहीं है और सुधार बहुत स्वागत योग्य हैं।

cat /dev/urandom | tr -dc 'ATGC' | fold -w 64 | awk 'NR>100000{exit}{printf NR"\t"$0"\n"}' > infile

2
मुझे यह बताना चाहिए कि प्रदर्शन के लिए आपके सभी विकल्पों की गणना करना उतना ही बेकार हो सकता है जितना कि पहली चीज जो दिमाग में आती है। awkदसियों लाख से कम के लिए अभी भी एक अच्छा जवाब है। यहां तक ​​कि अगर आप [रैखिक रूप से] एक बिलियन लाइनों तक स्केल करते हैं, तो सी केवल आपको 1.5 घंटे पर्ल और 3.6 घंटे से अधिक की बचत कर रहा है।
ओली

अब मेरी सी ++ संस्करण है पर है तो बहुत तेजी से, हो सकता है मैं सी ++ विशाल डेटा सेट्स के और अधिक सरल पाठ संसाधन के लिए विचार करना चाहते हैं। जब आप अरबों लाइनों में पहुँच जाते हैं तो यह लगभग दोगुना होता है और कई घंटों का अंतर होता है।
ओली



1
मुझे लगता है कि आपके परीक्षण दोहन की पीढ़ी की गति यादृच्छिक संख्या जनरेटर से बंधी है। आप इसे प्रत्येक संख्या का उपयोग करके इसे तेज बना सकते हैं या एक सजातीय वितरण उत्पन्न कर सकते हैं, जैसे paste <(yes A) <(yes T) <(yes G) <(yes C) | head -n1600000 | tr '\t' '\n' | shuf | tr -d \\n | fold -w64 | cat -n > infile:।
थोर

13

शुद्ध खोल कार्यान्वयन:

while read -r filename content ; do
    printf '%s\n' "$content" >> "${filename}.seq"
done < /source/file

12

का उपयोग कर awk:

awk '{printf "%s\n", $2>$1".seq"}' file

नामांकित से file, प्रत्येक रिकॉर्ड में दूसरे क्षेत्र ( $2) में पहले फ़ील्ड के नाम वाली फ़ाइल ( $1) .seqनाम के साथ जोड़ा गया प्रिंट करें।

जैसा कि थोर टिप्पणियों में बताते हैं , एक बड़े डेटासेट के लिए, आप फ़ाइल विवरणकों को समाप्त कर सकते हैं, इसलिए लिखने के बाद प्रत्येक फ़ाइल को बंद करना बुद्धिमानी होगी :

awk '{printf "%s\n", $2>$1".seq"; close($1".seq")}' file

नमस्ते यह काम करता है बहुत बहुत धन्यवाद .. क्या आप कोड को थोड़ा समझा सकते हैं?
user3138373

@ user3138373 आशा है कि मदद करता है ...
jasonwryan

यह मदद करता है .. धन्यवाद क्यों प्रिंट के बजाय काम नहीं करेगा प्रिंट ??
user3138373

3
यदि कई लाइनें हैं, तो सभी उपलब्ध फ़ाइल डिस्क्रिप्टर का उपयोग किया जाएगा, इसलिए आपको संभवतः एक जोड़ना चाहिए close($1".seq")
थोर

1
@ थोर, सच। कुछ awkकार्यान्वयन जैसे कि जीएनयू को पता है कि उसके आसपास कैसे काम करना है।
स्टीफन चेजलस

3

यहाँ एक तरीका है जिसे आप GNU sed के साथ कर सकते हैं:

<infile sed -r 's:(\w+)\s+(\w+):echo \2 > \1.seq:e; d'

या अधिक कुशलता से, जैसा कि ग्लेन जैकमैन द्वारा सुझाया गया है :

<infile sed -r 's:(\w+)\s+(\w+):echo \2 > \1.seq:' | sh

1
जबकि यह शांत है, यह काफी अक्षम है, हर पंक्ति के लिए एक बाहरी कमांड स्पॉन करने के लिए। यह बेहतर होगा कि सभी कच्चे कमांड में
सेड

1
@glennjackman: यह करने का सिर्फ एक दिलचस्प वैकल्पिक तरीका था। यदि इनपुट बड़ा है, awkतो संभवतः उपयोग करने के लिए सबसे कुशल उपकरण है। आप निश्चित रूप से shप्रत्येक पंक्ति के लिए स्पॉनिंग नहीं करने के बारे में सही हैं , मैंने विकल्प के रूप में पाइप-विकल्प को जोड़ा है।
थोर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.