প্রতিটি লাইনের অংশ আলাদা আলাদা ফাইলে আউটপুট করুন


14

আমার কাছে এই জাতীয় একটি ফাইল রয়েছে:

a   AGTACTTCCAGGAACGGTGCACTCTCC
b   ATGGATTTTTGGAGCAGGGAGATGGAATAGGAGCATGCTCCAT
c   ATATTAAATGGATTTTTGGAGCAGGGAGATGGAATAGGAGCATGCTCCATCCACTCCACAC
d   ATCAGTTTAATATCTGATACGTCCTCTATCCGAGGACAATATATTAAATGGA
e   TTTGGCTAAGATCAAGTGTAGTATCTGTTCTTATAAGTTTAATATCTGATATGTCCTCTATCTGA

আমি ফাইল তৈরি করতে চাই a.seqযার ক্রম রয়েছে AGTACTTCCAGGAACGGTGCACTCTCC। একইভাবে b.seqরয়েছে ATGGATTTTTGGAGCAGGGAGATGGAATAGGAGCATGCTCCAT। সংক্ষেপে, কলাম 1 এক্সটেনশান সহ আউটপুট ফাইলের নাম হিসাবে ব্যবহার করা উচিত .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

এক নজরে সি সবচেয়ে ভাল দেখায় তবে দ্রুত চালাতে পুকুরটি শূকর। আপনি বহু বিলিয়ন লাইনের কথা না বললে পাইপি এবং সি ++ যথেষ্ট ভাল লেখা এবং সম্পাদন করা অনেক সহজ । যদি তা হয়ে থাকে তবে র‍্যামে বা এসএসডি-তে এই সমস্ত কিছু করার একটি আপগ্রেড কোডের উন্নতির চেয়ে ভাল বিনিয়োগ হতে পারে।

স্পষ্টতই আমি এইগুলির মধ্য দিয়ে যাবার সময়টি আপনি সম্ভবত সবচেয়ে ধীর বিকল্পে কয়েকশ মিলিয়ন রেকর্ড প্রক্রিয়া করতে পারেন । আপনি যদি কেবল লিখতে awkবা বাশ লুপ করতে পারেন তবে তা করুন এবং জীবন নিয়ে চলুন। আমার স্পষ্টতই আজ অতিরিক্ত সময় ছিল।

আমি কয়েকটি মাল্টি-থ্রেডেড অপশন (সি ++ এবং পাইথন এবং জিএনইউ সহ হাইব্রিডগুলিতেও 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বাইনারি কেবল পাইথনের বাস্তবায়ন নয়। আমি যখন পাইপির মাধ্যমে এই একই পরীক্ষাটি চালিয়েছি তখন আর কোনও যুক্তি অপ্টিমাইজেশন ছাড়াই এটি সি এর চেয়ে দ্রুত ছিল । পাইথনকে "ধীর ভাষা" হিসাবে লেখার আগে এটি মনে রাখবেন।

সি

আমি আমার সিপিইউটি আসলে কী পেতে পারি তা দেখার জন্য আমি এই উদাহরণটি শুরু করেছিলাম তবে খোলামেলাভাবে, সি যদি আপনি একটি দীর্ঘ সময়ের মধ্যে এটি স্পর্শ না করেন তবে কোড কোডের জন্য দুঃস্বপ্ন। এটি 100-চর লাইনগুলিতে সীমাবদ্ধ হওয়ার অতিরিক্ত যুক্তি রয়েছে যদিও এটি প্রসারিত করা খুব সহজ, আমার কেবল এটির দরকার ছিল না।

আমার আসল সংস্করণটি সি ++ এবং পাইপির চেয়ে ধীর ছিল তবে এটি ব্লগ করার পরে আমি জুলিয়ান ক্লোডের কাছ থেকে কিছুটা সহায়তা পেয়েছি । এই সংস্করণটি এখন দ্রুততর হয়েছে কারণ এটির টুইটকৃত আইও বাফারগুলির কারণে। এটি অন্য যে কোনও কিছুর চেয়েও অনেক দীর্ঘ এবং জড়িত।

#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();
}

জিএনইউ সমান্তরাল

(মুর্টিল সংস্করণ নয়)। এটি একটি দুর্দান্ত সংক্ষিপ্ত বাক্য গঠন তবে ওএমজিএসএলও। আমি এটি ভুল ব্যবহার করা হতে পারে।

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

পরীক্ষার জোতা জেনারেটর

[এটিজিসি] * 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
Thor

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

হাই এটি অনেক ধন্যবাদ ধন্যবাদ .. আপনি কোডটি কিছুটা ব্যাখ্যা করতে পারেন?
ব্যবহারকারীর 13138373

@ ব্যবহারকারী3138373 আশা করি এটি সাহায্য করে ...
জেসনওয়ারিয়ান

এটি সাহায্য করে .. ধন্যবাদ প্রিন্টফের পরিবর্তে কেন মুদ্রণ কাজ করবে না ??
ব্যবহারকারীর 13138373

3
যদি অনেকগুলি লাইন থাকে, সমস্ত উপলব্ধ ফাইল বর্ণনাকারী ব্যবহৃত হবে, সুতরাং আপনার সম্ভবত একটি যুক্ত করা উচিত close($1".seq")
থোর

1
@ থোর, সত্য কিছু awkবাস্তবায়ন যেমন জিএনইউ'র কাছ থেকে কীভাবে কাজ করা যায় তা জানে।
স্টাফেন চেজেলাস

3

জিএনইউ সেডের সাহায্যে আপনি এটি করতে পারেন Here

<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প্রতিটি লাইনের জন্য স্প্যানিং না করার বিষয়ে অবশ্যই সঠিক , আমি পাইপ-বিকল্পটি বিকল্প হিসাবে যুক্ত করেছি।
থোর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.