স্ট্রিংটি একটি বিশাল (70 গিগাবাইট), এক লাইন, পাঠ্য ফাইলে প্রতিস্থাপন করুন


126

আমার কাছে বিশাল (70 গিগাবাইট), একটি লাইন , পাঠ্য ফাইল রয়েছে এবং আমি এতে একটি স্ট্রিং (টোকেন) প্রতিস্থাপন করতে চাই। আমি টোকেনটি <unk>অন্য একটি ডামি টোকেন ( গ্লোভ ইস্যু ) দিয়ে প্রতিস্থাপন করতে চাই ।

আমি চেষ্টা করেছি sed:

sed 's/<unk>/<raw_unk>/g' < corpus.txt > corpus.txt.new

তবে আউটপুট ফাইলটিতে corpus.txt.newশূন্য-বাইট রয়েছে!

আমি পার্ল ব্যবহার করার চেষ্টাও করেছি:

perl -pe 's/<unk>/<raw_unk>/g' < corpus.txt > corpus.txt.new

তবে আমি স্মৃতি ত্রুটির বাইরে চলে এসেছি।

ছোট ফাইলগুলির জন্য, উপরের দুটি কমান্ডই কাজ করে।

আমি একটি স্ট্রিং যেমন একটি ফাইল প্রতিস্থাপন করতে পারেন? এটি সম্পর্কিত সম্পর্কিত প্রশ্ন, তবে উত্তরগুলির কোনওটিই আমার পক্ষে কার্যকর হয়নি।

সম্পাদনা : 10 জিবি (বা যা কিছু) প্রতিটি অংশে ফাইলটি বিভক্ত করা এবং sedতাদের প্রতিটিটিতে প্রয়োগ এবং তারপরে মার্জ করার বিষয়ে catকী? যে জানার জন্য? এর থেকেও কি আরও সুন্দর সমাধান?


@ গিলিস যেমন উল্লেখ করেছেন, আপনি কি এমন কিছু পুনরাবৃত্তি চরিত্র সনাক্ত করতে পারেন যা আপনার একক বড় লাইনে একটি কাস্টম ডিলিমিটার হিসাবে পরিবেশন করতে পারে?
রোমানপেরেখারেস্ট

আমি ভাবছি যে এমন একটি সরঞ্জাম যা কেবল অনুসন্ধান এবং প্রতিস্থাপন করতে পারে তবে আরও জটিল রেজেেক্স নয়, দ্রুততর হবে। এটি একবারে কোনও লাইন তৈরি করেও উপকৃত হবে না, সুতরাং এই ফাইলটিতে শ্বাসরোধ করবে না। দুর্ভাগ্যক্রমে আমার কাছে এই জাতীয় সরঞ্জামটির অস্তিত্ব সম্পর্কে কোনও ধারণা নেই, যদিও এটি লেখা শক্ত হবে না। যদি এটি বন্ধ হয় তবে উত্তরগুলির মধ্যে একটি হিসাবে নতুন লাইনের চরিত্রগুলিকে স্থান দেওয়া সম্ভবত সবচেয়ে সহজ হবে।
ctrl-alt-delor 15

আপনার ফাইলটিতে এএসসিআইআই ব্যতীত অন্য কিছু রয়েছে? যদি তা হয় তবে সমস্ত ইউনিকোড হ্যান্ডলিং বাদ দেওয়া যেতে পারে এবং কাঁচা বাইটগুলি প্রক্রিয়া করা যেতে পারে।
প্যাট্রিক বুচার

আমি @ পেট্রিকবাচারের সাথে একমত একটি বড় ছবি দেখুন। এই পাঠ্যটি প্রতিস্থাপনের তাত্ক্ষণিক প্রয়োজন ছাড়াও এই ফাইলটি আর কী ব্যবহার করার কথা রয়েছে? যদি এটি কোনও প্রকারের লগ হয় তবে কেউ এর সাথে কার্যকরভাবে কাজ করতে সক্ষম হবে না। যদি এটি কোনও ডেটা ফাইল হয় যা কিছু অ্যাপ্লিকেশন ব্যবহার করে, তবে সেই অ্যাপ্লিকেশনটির সেই ফাইলের ডেটা বজায় রাখার দায়িত্ব রাখা উচিত।
থমাস কার্লিসেল

2
আপনি ব্যবহার করতে পারেন splitসঙ্গে -bবিকল্প বাইটে খণ্ড ফাইলের মাপ সংজ্ঞা। প্রতিটি পরিবর্তে ব্যবহার করে প্রক্রিয়া করুন sedএবং পুনরায় একত্রিত হন। একটি ঝুঁকি রয়েছে যে <unk>দুটি ফাইলে বিভক্ত হতে পারে এবং তা খুঁজে পাওয়া যাবে না ...
ভ্লাদিস্লাভস ডভগ্যালিক্স

উত্তর:


106

সাধারণ পাঠ্য প্রক্রিয়াকরণ সরঞ্জামগুলি এমন লাইনগুলি হ্যান্ডেল করার জন্য ডিজাইন করা হয় না যা র্যামের সাথে খাপ খায় না। তারা একটি রেকর্ড (এক লাইন) পড়ে, এটিকে পরিচালনা করে এবং ফলাফল আউটপুট করে কাজ করে, তারপরে পরবর্তী রেকর্ডে (লাইন) এগিয়ে যায় work

যদি কোনও এএসসিআইআই অক্ষর থাকে যা ফাইলটিতে প্রায়শই উপস্থিত হয় এবং উপস্থিত হয় না <unk>বা থাকে <raw_unk>, তবে আপনি এটি রেকর্ড বিভাজক হিসাবে ব্যবহার করতে পারেন। যেহেতু বেশিরভাগ সরঞ্জাম কাস্টম রেকর্ড বিভাজকগুলিকে অনুমতি দেয় না, তাই চরিত্রটি এবং নিউলাইনগুলির মধ্যে অদলবদল করে। trলাইনগুলি নয়, বাইটগুলি প্রসেস করে তাই এটি কোনও রেকর্ড আকারের বিষয়ে চিন্তা করে না। ধরুন যে ;কাজ করে:

<corpus.txt tr '\n;' ';\n' |
sed 's/<unk>/<raw_unk>/g' |
tr '\n;' ';\n' >corpus.txt.new

আপনি যে পাঠ্যের সন্ধান করছেন সেটির প্রথম চরিত্রটিও নোঙ্গর করতে পারেন, ধরে নেওয়া যে এটি অনুসন্ধানের পাঠ্যে পুনরাবৃত্তি হয়নি এবং এটি প্রায়শই যথেষ্ট দেখা যায়। যদি ফাইলটি শুরু হতে পারে তবে একটি স্পিউরিয়াস ম্যাচ এড়ানোর unk>জন্য সেড কমান্ডটি পরিবর্তন করুন sed '2,$ s/…

<corpus.txt tr '\n<' '<\n' |
sed 's/^unk>/raw_unk>/g' |
tr '\n<' '<\n' >corpus.txt.new

বিকল্পভাবে, শেষ অক্ষরটি ব্যবহার করুন।

<corpus.txt tr '\n>' '>\n' |
sed 's/<unk$/<raw_unk/g' |
tr '\n>' '>\n' >corpus.txt.new

মনে রাখবেন যে এই কৌশলটি ধরে নিয়েছে যে একটি ফাইল কোনও নিউলাইনের সাথে শেষ হয় না এমন কোনও সিস্টেমে নির্বিঘ্নে সঞ্চালিত হয়, অর্থাত্ এটি এটি কাটা ছাড়াই এবং একটি চূড়ান্ত নিউলাইন যুক্ত না করে শেষ আংশিক লাইনটি প্রক্রিয়া করে। এটি জিএনইউ সেডের সাথে কাজ করে। আপনি যদি রেকর্ড বিভাজক হিসাবে ফাইলের শেষ চরিত্রটি চয়ন করতে পারেন তবে আপনি কোনও বহনযোগ্যতা এড়াতে পারবেন।


8
পরীক্ষার জন্য আমার কাছে এ জাতীয় কোনও ফাইল নেই তবে আপনি ওওকে "রেকর্ড বিভাজক" এবং "আউটপুট রেকর্ড পৃথককারী" নির্দিষ্ট করতে পারেন। সুতরাং ধরে নিচ্ছি যে আপনার ফাইলে কমাগুলির একটি শালীন ছদ্মবেশ রয়েছে, আপনি সম্ভবত এটি দিয়ে সমাধান করতে পারবেন: awk -v RS=, -v ORS=, '{gsub(/<unk>/, "<raw_unk>"); print}' না?
ওয়াইল্ডকার্ড

4
@ উইল্ডকার্ড হ্যাঁ, এটি অন্য একটি সমাধান। আওক সিডের চেয়ে ধীর গতিতে থাকে, এজন্য আমি এটিকে বিশাল ফাইলের জন্য পছন্দসই সমাধান হিসাবে প্রস্তাব দিই না।
গিলস

আপনি কমান্ড লাইন বিকল্প পার্ল রেকর্ড বিভাজক সেট করতে পারেন -0এবং একটি গৃহস্থালি অকট্যাল মান, বা স্ক্রিপ্ট ভিতরে এটি সঙ্গে বিশেষ পরিবর্তনশীল নির্ধারণ করা যাবে$/
beasy

@ গিলস: তবে awkদু'বার স্ট্রিমটি পাস করা এড়ানো ব্যবহার করুন tr। তাহলে কি এটি এখনও ধীর হবে?
ব্যবহারকারী 285259

2
@ user285259 সাধারণত না। trখুব দ্রুত এবং পাইপটিও সমান্তরাল হতে পারে।
গিলস

110

এত বড় ফাইলের জন্য একটি সম্ভাবনা হ'ল ফ্লেক্স। যাক unk.l:

%%
\<unk\>     printf("<raw_unk>");  
%%

তারপরে সংকলন এবং কার্যকর করুন:

$ flex -o unk.c  unk.l
$ cc -o unk -O2 unk.c -lfl
$ unk < corpus.txt > corpus.txt.new

5
makeএর জন্য ডিফল্ট নিয়ম রয়েছে, ফ্লেক্স / সিসির পরিবর্তে আপনি %option mainunk.l এর প্রথম লাইন হিসাবে একটি যুক্ত করতে পারেন এবং তারপরে ঠিক make unk। আমি আরো-অর-কম reflexively ব্যবহার %option main 8bit fast, এবং export CFLAGS='-march=native -pipe -Os'আমার মধ্যে .bashrc
jthill

1
@undercat: যদি এটি অফ-টপিক না হয়, আমি আপনাকে জলের-স্তরের সমস্যা সমাধান থেকে শুরু করে বিশেষ-উদ্দেশ্যে ইনপুট পার্সিংয়ের ক্ষেত্রে অনেকগুলি নন-কম্পাইলার ফ্রন্ট এন্ড অ্যাপ্লিকেশনগুলি দেখাতে পারি। আপনি যদি বাক্সের বাইরে কিছুটা
ভাবেন

@ জেথিল, আপনাকে ধন্যবাদ: %option main+ make+ allyচ্ছিকভাবে CFLAGSখুব সুন্দর কৌশল! কি -march=nativeডিফল্ট আচরণ?
জাজাও

1
@ জামেস্কফ যেমন আপনি বলেছিলেন - বিষয়টিকে প্রশ্নবিদ্ধ করা শক্ত হবে - তবে আমি এটিও দেখতে চাই
স্টিভেন পেনি

1
@ জামেস্কেফ ইউনিয়নে আমার একজন প্রফেসর এমন একটি সরঞ্জাম তৈরি করতে ফ্লেক্স ব্যবহার করেছেন যা কারখানার জন্য ফ্যাব্রিকের প্রকারের স্বীকৃতি দেয়! এই জাতীয় কিছু জিজ্ঞাসা সম্পর্কে কীভাবে: "ফ্লেক্সটি একটি খুব শক্তিশালী সরঞ্জামের মতো মনে হয় তবে আমি কোনও সংকলক / পার্সার লিখতে পারি না - ফ্লেক্সের জন্য অন্য কোনও ব্যবহারের মামলা আছে কি?"
পল ইভান্স

41

সুতরাং আপনার কাছে পুরো ফাইলটি একবারে ধরে রাখতে পর্যাপ্ত শারীরিক মেমরি (র‌্যাম) নেই, তবে একটি 64-বিট সিস্টেমে আপনার পুরো ফাইলটি মানচিত্র করার জন্য যথেষ্ট ভার্চুয়াল ঠিকানার স্থান রয়েছে। ভার্চুয়াল ম্যাপিংগুলি এরকম ক্ষেত্রে সাধারণ হ্যাক হিসাবে কার্যকর হতে পারে।

প্রয়োজনীয় অপারেশনগুলি সমস্ত পাইথনের অন্তর্ভুক্ত। বেশ কয়েকটি বিরক্তিকর সূক্ষ্মতা রয়েছে তবে এটি সি কোড লিখতে এড়াতে পারে না। বিশেষত, মেমরির মধ্যে ফাইলটি অনুলিপি করা এড়াতে যত্ন নেওয়া প্রয়োজন, যা পয়েন্টটি পুরোপুরি পরাস্ত করবে। প্লাস সাইডে, আপনি নিখরচায় ত্রুটি-প্রতিবেদন পান (অজগর "ব্যতিক্রম") :) :)

#!/usr/bin/python3
# This script takes input from stdin
# (but it must be a regular file, to support mapping it),
# and writes the result to stdout.

search = b'<unk>'
replace = b'<raw_unk>'


import sys
import os
import mmap

# sys.stdout requires str, but we want to write bytes
out_bytes = sys.stdout.buffer

mem = mmap.mmap(sys.stdin.fileno(), 0, access=mmap.ACCESS_READ)
i = mem.find(search)
if i < 0:
    sys.exit("Search string not found")

# mmap object subscripts to bytes (making a copy)
# memoryview object subscripts to a memoryview object
# (it implements the buffer protocol).
view = memoryview(mem)

out_bytes.write(view[:i])
out_bytes.write(replace)
out_bytes.write(view[i+len(search):])

যদি আমার সিস্টেমে 8 গিগাবাইটের মধ্যে প্রায় 4 জিবি রেজাল্ট মেমোরি থাকে তবে মেম = এমএএমপি.এম্যাপ (এসএসটিডিন.ফিলেনো (), 0, অ্যাক্সেস = এমএমএপি.এসিসিএসএসএএডি 72AD) এর অর্থ কি এটি সেই জায়গাতে ডেটা রাখে? বা এটি অনেক কম হবে (1 জিবি?)>
রাহুল

1
@ রাহুল "সুতরাং আপনার পর্যাপ্ত র‌্যাম নেই, তবে একটি 64-বিট সিস্টেমে আপনার পুরো ফাইলটি মানচিত্র করার জন্য পর্যাপ্ত ভার্চুয়াল ঠিকানার জায়গা রয়েছে।" এটি চাহিদা অনুসারে শারীরিক মেষের বাইরে এবং বাইরে পৃষ্ঠাযুক্ত (বা এর অভাব)। এই প্রোগ্রামটির কোনও বৃহত পরিমাণ শারীরিক র‍্যামের প্রয়োজন ছাড়াই কাজ করা উচিত। Physical৪-বিট সিস্টেমে সর্বাধিক শারীরিক র‌্যামের চেয়ে অনেক বেশি ভার্চুয়াল ঠিকানার স্থান রয়েছে। এছাড়াও প্রতিটি চলমান প্রক্রিয়াটির নিজস্ব ভার্চুয়াল ঠিকানার স্থান রয়েছে। এর অর্থ হ'ল ভার্চুয়াল অ্যাড্রেস স্পেসের পুরোপুরি চলমান কোনও জিনিস নয়, এটি কোনও বৈধ ধারণা নয়।
সোর্সজেডি

4
@ রাহুল হাঁ! পাইথন এমএমএপি.এমএ্যাপ () হ'ল সি ফাংশন এমএম্যাপ () এর চারপাশে মোটামুটি পাতলা মোড়ক। এবং এমএমএপ () হ'ল এক্সিকিউটেবলগুলি চালনার জন্য ব্যবহৃত একই পদ্ধতি এবং ভাগ করা লাইব্রেরি থেকে কোড।
সোর্সজেডি

2
@ জামেস্কেফ আমি ভুল হতে পারি, তবে আমি অনুভব করি এটি কেবল একটি ব্যক্তিগত পছন্দ। যেহেতু পারফরম্যান্স ক্ষতির পরিমাণ নগণ্য হবে (কারণ তিনি বলেছিলেন যে ফাংশনটি আসল সি ফাংশনকে ডাকে) তাই ওভারহেডের অপচয় হ্রাস খুব কম হয়, কারণ এর মধ্যে অন্য কোনও জিনিস ঘটছে না। সি আরও ভাল হত, তবে এই সমাধানটি কেবলমাত্র আরও বড় এবং কঠিন 70 জিবি ইস্যু সমাধানের জন্য অনুকূলিতকরণের উদ্দেশ্যে নয়।
রাহুল

1
সাধারণভাবে পাইথনে লেখা আরও কমপ্যাক্ট। এক্ষেত্রে এটি প্রমাণিত হয়েছে যে অজগর সংস্করণে কয়েকটি বিবরণ রয়েছে এবং সি সংস্করণটি লিখতে ভাল লাগছিল। (যদিও এটি এত সহজ নয় তবে যদি searchকোনও নুল অক্ষর ধারণ করতে পারে And এবং আমি লক্ষ্য করেছি যে এখানে অন্যান্য সি সংস্করণটি NUL অক্ষরগুলিকে সমর্থন করে না replace)) তুলনা করার উদ্দেশ্যে সি সংস্করণটি উত্সাহিত করতে আপনাকে খুব স্বাগত জানাই। তবে মনে রাখবেন যে আমার সংস্করণে এটি সম্পাদন করে এমন অপারেশনগুলির জন্য প্রাথমিক ত্রুটি প্রতিবেদন অন্তর্ভুক্ত করে। সি ভার্সন আইএমও পড়তে কমপক্ষে আরও বিরক্তিকর হবে , যখন ত্রুটি প্রতিবেদন অন্তর্ভুক্ত করা হয়।
সোর্সজেদি

17

আমি মনে করি সি সংস্করণটি আরও ভাল পারফর্ম করতে পারে:

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

#define PAT_LEN 5

int main()
{
    /* note this is not a general solution. In particular the pattern
     * must not have a repeated sequence at the start, so <unk> is fine
     * but aardvark is not, because it starts with "a" repeated, and ababc
     * is not because it starts with "ab" repeated. */
    char pattern[] = "<unk>";          /* set PAT_LEN to length of this */
    char replacement[] = "<raw_unk>"; 
    int c;
    int i, j;

    for (i = 0; (c = getchar()) != EOF;) {
        if (c == pattern[i]) {
            i++;
            if (i == PAT_LEN) {
                printf("%s", replacement);
                i = 0;
            }
        } else {
            if (i > 0) {
                for (j = 0; j < i; j++) {
                    putchar(pattern[j]);
                }
                i = 0;
            }
            if (c == pattern[0]) {
                i = 1;
            } else {
                putchar(c);
            }
        }
    }
    /* TODO: fix up end of file if it ends with a part of pattern */
    return 0;
}

সম্পাদনা: মন্তব্যসমূহের পরামর্শ অনুসারে সংশোধিত। প্যাটার্ন সহ স্থির বাগও <<unk>


2
আপনি (বুফ [জে]) এর পরিবর্তে (প্যাটার্ন [জে]) মুদ্রণ করতে পারেন (তারা এই মুহুর্তে সমান, সুতরাং আপনার বাফার দরকার নেই
RiaD

3
এছাড়াও কোড স্ট্রিং এর জন্য কাজ করবে না "<< Unk>" ideone.com/ncM2yy
riad

10
30 এমবি 0.3 সেকেন্ডে? এটি কেবল 90 এমবি / সেকেন্ড। memcpyগতি (অর্থাত মেমরির বাধা) 12GB / সেকেন্ডের মতো সাম্প্রতিক x86 সিপিইউতে (উদাহরণস্বরূপ স্কাইলেক)। এমনকি ডিস্ক ক্যাশে গরম 30MB ফাইলের জন্য stdio + সিস্টেম কল ওভারহেড থাকা সত্ত্বেও, একটি দক্ষ বাস্তবায়নের জন্য আমি সম্ভবত 1GB / সেকেন্ডের আশা করছিলাম আপনি কী অপটিমাইজেশন অক্ষম করেছেন, বা এক-চরিত্রে আই / ও-তে আসলেই ধীরগতির সাথে সংকলন করেছেন? getchar_unlocked/ putchar_unlockedসাহায্য করতে পারে, তবে সম্ভবত 128kiB (বেশিরভাগ x86 সিপিইউতে এল 2 ক্যাশে আকারের অর্ধেক, যাতে আপনি বেশিরভাগ পড়ার পরে লুপিংয়ের সময় এল 2 তে আঘাত করেন)
পিটার

2
আমার মাথা, getchar, শীর্ষ এবং putchar থেকে হয় ধীর।
রুই এফ রিবেইরো

3
fixজন্য প্রোগ্রাম "<<unk>"এখনও যদি কাজ না করে patternঅক্ষরের একটি পুনরাবৃত্তি ক্রম দিয়ে শুরু হয় (অর্থাত যদি আপনি জেব্রা সঙ্গে aardvark প্রতিস্থাপন করার চেষ্টা করছিলেন কাজ করবে না এবং আপনি aaardvak ইনপুট ছিল, অথবা আপনি ababc প্রতিস্থাপন করার চেষ্টা করছিলেন এবং abababc এর ইনপুট ছিল)। সাধারণত আপনি যতটা অক্ষর পড়েছেন তার সংখ্যা নিয়ে আপনি এগিয়ে যেতে পারবেন না আপনি যদি না জানেন যে আপনি যে অক্ষরগুলি পড়েছেন তার মধ্যে কোনও মিলের সম্ভাবনা নেই।
আইক্রাস

16

replaceমারিয়্যাডবি-সার্ভার / মাইএসকিএল-সার্ভার প্যাকেজে একটি ইউটিলিটি রয়েছে। এটি সরল স্ট্রিংগুলি (নিয়মিত প্রকাশ নয়) প্রতিস্থাপন করে এবং গ্রেপ / সেড / অ্যাডকের বিপরীতে এবং এর replaceবিষয়ে যত্ন করে না । যেকোন ইনপুট ফাইল (আমার মেশিনে প্রায় 400 কিলোবাইট) সহ মেমরির খরচ ক্রমাগত।\n\0

অবশ্যই আপনার ব্যবহারের জন্য একটি মাইএসকিএল সার্ভার চালানোর দরকার নেই replace, এটি কেবল ফেডোরায় সেইভাবে প্যাকেজ করা আছে। অন্যান্য ডিস্ট্রোজ / অপারেটিং সিস্টেমগুলি এটি পৃথকভাবে প্যাকেজ করে থাকতে পারে।


14

জিএনইউ grepআপনাকে "বাইনারি" ফাইলগুলিতে ম্যাচের অফসেট প্রদর্শন করতে পারে, স্মৃতিতে পুরো রেখা না পড়ে। তারপরে ddআপনি এই অফসেটটি পড়তে ব্যবহার করতে পারেন, ম্যাচটি এড়িয়ে যান, তারপরে ফাইলটি থেকে অনুলিপি চালিয়ে যেতে পারেন।

file=...
newfile=...
replace='<raw_unk>'
grep -o -b -a -F '<unk>' <"$file" |
(   pos=0
    while IFS=$IFS: read offset pattern
    do size=${#pattern}
       let skip=offset-pos
       let big=skip/1048576
       let skip=skip-big*1048576
       dd bs=1048576 count=$big <&3
       dd bs=1 count=$skip <&3
       dd bs=1 count=$size of=/dev/null <&3
       printf "%s" "$replace"
       let pos=offset+size
    done
    cat <&3
) 3<"$file" >"$newfile"

গতির জন্য, আমি ddব্লকসাইজ 1048576 এর বড় রিডে এবং একবারে 1 বাইটের আরও ছোট পড়াতে বিভক্ত করেছি , তবে এত বড় ফাইলটিতে এই অপারেশনটি এখনও কিছুটা ধীর হবে। grepআউটপুট উদাহরণস্বরূপ, হয়, 13977:<unk>এবং এই ভেরিয়েবল মধ্যে পড়তে দ্বারা কোলন উপর বিভক্ত করা offsetএবং patternposফাইল থেকে ইতিমধ্যে কয়টি বাইট অনুলিপি করা হয়েছে সে সম্পর্কে আমাদের নজর রাখতে হবে ।


11

এখানে আরও একটি একক ইউনিক্স কমান্ড লাইন রয়েছে যা অন্যান্য বিকল্পের চেয়ে ভাল পারফরম্যান্স করতে পারে কারণ আপনি "ব্লক আকার" এর জন্য "শিকার" করতে পারেন যা ভাল পারফর্ম করে। এটি শক্তিশালী হওয়ার জন্য আপনাকে জানতে হবে যে প্রতি এক্স অক্ষরে আপনার কমপক্ষে একটি স্থান রয়েছে যেখানে এক্স আপনার নির্বিচারে "ব্লক আকার" size নীচের উদাহরণে আমি 1024 অক্ষরের একটি "ব্লক আকার" চয়ন করেছি।

fold -w 1024 -s corpus.txt | sed 's/<unk>/<raw_unk>/g' | tr '/n' '/0'

এখানে, ভাঁজটি 1024 বাইট অবধি উঠবে , তবে শেষের বিরতি থেকে কমপক্ষে একটি থাকলে সেখানে -s নিশ্চিত করে যে এটি কোনও স্পেসে ভেঙে গেছে।

সিড কমান্ডটি আপনার এবং আপনি যা প্রত্যাশা করেন তা করে।

তারপরে টিআর কমান্ড ফাইলটিকে নতুন কিছুকে রূপান্তরিত করবে যা কিছুতেই ফিরে আসে নি।

এটি আরও দ্রুত সম্পাদন করে কিনা তা দেখতে আপনার আরও বড় ব্লক মাপগুলি চেষ্টা করা বিবেচনা করা উচিত। 1024 এর পরিবর্তে, আপনি ভাঁজের বিকল্পের জন্য 10240 এবং 102400 এবং 1048576 ব্যবহার করতে পারেন।

এখানে প্রতিটি পদক্ষেপের দ্বারা বিভক্ত একটি উদাহরণ রয়েছে যা সমস্ত এন এর লোকেসকে রূপান্তর করে:

[root@alpha ~]# cat mailtest.txt
test XJS C4JD QADN1 NSBN3 2IDNEN GTUBE STANDARD ANTI UBE-TEST EMAIL*C.34X test

[root@alpha ~]# fold -w 20 -s mailtest.txt
test XJS C4JD QADN1
NSBN3 2IDNEN GTUBE
STANDARD ANTI
UBE-TEST
EMAIL*C.34X test

[root@alpha ~]# fold -w 20 -s mailtest.txt | sed 's/N/n/g'
test XJS C4JD QADn1
nSBn3 2IDnEn GTUBE
STAnDARD AnTI
UBE-TEST
EMAIL*C.34X test

[root@alpha ~]# fold -w 20 -s mailtest.txt | sed 's/N/n/g' | tr '\n' '\0'
test XJS C4JD QADn1 nSBn3 2IDnEn GTUBE STAnDARD AnTI UBE-TEST EMAIL*C.34X test

ফাইলের একটি থাকলে আপনার একেবারে শেষের দিকে একটি নিউলাইন যুক্ত করতে হবে, কারণ টিআর কমান্ড এটি মুছে ফেলবে।


1
আপনি কীভাবে নিশ্চিত করতে পারেন যে প্রান্তের ক্ষেত্রে যেখানে পর্যাপ্ত পরিমাণে সাদা জায়গা নেই সেখানে আপনি সেই প্যাটার্নটি ভঙ্গ করছেন না?
রেক্যান্ডবোনম্যান

1
যেমনটি বলা হয়েছে, এটি শক্তিশালী হওয়ার জন্য প্রতিটি এক্স অক্ষরে কমপক্ষে একটি স্থান থাকা দরকার। আপনি চয়ন করতে পারেন যে কোনও ব্লক আকারের সাহায্যে আপনি সেই বিশ্লেষণটি যথেষ্ট সহজ করতে পারবেন: ভাঁজ-ডাব্লু এক্স মেলেস্টেস্ট.টেক্সট | গ্রেপ-ভি "" | ডাব্লুসি-এল এটি যে নম্বরটি দেয় তা হ'ল সম্ভাব্য প্রান্তের ক্ষেত্রে ভাঁজ করা লাইনের সংখ্যা। যদি এটি শূন্য হয় তবে সমাধানটি কাজের গ্যারান্টিযুক্ত।
আলফ্রিমা

10

ব্যবহার perl

আপনার নিজের বাফার পরিচালনা করা

আপনি ব্যবহার করতে পারেন IO::Handle'র setvbufডিফল্ট বাফার পরিচালনা করতে, অথবা আপনি সঙ্গে আপনার নিজের বাফার পরিচালনা করতে পারেন sysreadএবং syswrite। চেক করুন perldoc -f sysreadএবং perldoc -f syswriteআরও তথ্যের জন্য, তারা মূলত বাফার ছাড়েন Io।

এখানে আমরা আমাদের নিজস্ব বাফার আইও রোল করি তবে আমরা এটি ম্যানুয়ালি এবং নির্বিচারে 1024 বাইটে করি। আমরা ফাইলটি আরডাব্লুয়ের জন্যও খুলি তাই আমরা একবারে একই এফএইচে এটি করি।

use strict;
use warnings;
use Fcntl qw(:flock O_RDWR);
use autodie;
use bytes;

use constant CHUNK_SIZE => 1024 * 32;

sysopen my $fh, 'file', O_RDWR;
flock($fh, LOCK_EX);

my $chunk = 1;
while ( sysread $fh, my $bytes, CHUNK_SIZE * $chunk ) {
  if ( $bytes =~ s/<unk>/<raw_unk>/g ) {
    seek( $fh, ($chunk-1)* CHUNK_SIZE, 0 );
    syswrite( $fh, $bytes, 1024);
    seek( $fh, $chunk * CHUNK_SIZE, 0 );
  }
  $chunk++;
}

আপনি যদি এই পথে যেতে যাচ্ছেন

  1. নিশ্চিত করুন <unk>এবং <raw_unk>একই বাইট আকার।
  2. আপনি নিশ্চিত করতে চাইতে পারেন যে আমাদের বাফার পদ্ধতিটি CHUNKSIZEযদি 1 বাইটের বেশি প্রতিস্থাপন করে থাকে তবে সীমাটি অতিক্রম করবেন না ।

2
<unk>খণ্ডগুলির মধ্যে একটি সীমানা পড়ে যদি ?
লিওরি

8

আপনি বিবি ( বাইনারি ব্লক সম্পাদক ) চেষ্টা করতে পারেন , একটি " sedবাইনারি ফাইলগুলির জন্য"।

কোনও অক্ষরবিহীন একটি 7GB টেক্সট ফাইলে এটি ব্যবহার করে আমি ভাল সাফল্য পেয়েছি EOL, একটি স্ট্রিংয়ের একাধিক ঘটনাকে আলাদা দৈর্ঘ্যের একটিকে প্রতিস্থাপন করে। কোনও অপ্টিমাইজেশনের চেষ্টা ছাড়াই এটি>> 50 এমবি / সেকেন্ডের গড় প্রসেসিং থ্রুপুট দেয়।


5

এর সাথে perlআপনি স্থির দৈর্ঘ্যের রেকর্ডগুলির সাথে কাজ করতে পারেন যেমন:

perl -pe 'BEGIN{$/=\1e8}
          s/<unk>/<raw_unk>/g' < corpus.txt > corpus.txt.new

এবং আশা করি যে <unk>এই 100MB রেকর্ডগুলির মধ্যে দুটি জুড়ে বিস্তৃত হবে না ।


আমিও এই পদ্ধতিটি সম্পর্কে ভাবছিলাম, তবে এটি while read -N 1000 chunk;( 1000উদাহরণ হিসাবে বেছে নেওয়া) ব্যবহার করছি। <unk>খণ্ডগুলির মধ্যে ভাঙা সমাধানের জন্য ফাইলটি দুটি পাস হয়: প্রথমটি 100MB অংশ এবং দ্বিতীয়টি '100MB + 5 বাইট' খণ্ড দিয়ে with তবে এটি 70 গিগাবাইট ফাইলের ক্ষেত্রে সর্বোত্তম সমাধান নয়।
মিনিম্যাক্স

3
আপনার এমনকি দুটি পাসের দরকার নেই। ব্লক পড়ুন ক। ইওএফ না থাকাকালীন, বি ব্লকটি পড়ুন, অনুসন্ধান করুন / এ + বি প্রতিস্থাপন করুন উ: = বি লুপ। জটিলতা আপনাকে প্রতিস্থাপনের অভ্যন্তরে প্রতিস্থাপন করবে না তা নিশ্চিত করছে।
রোয়াইমা

@ মনিম্যাক্স, দ্বিতীয় পাসটি অগত্যা সহায়তা করবে না কারণ প্রথম পাসটিতে প্রতিটি ঘটনার জন্য 5 বাইট যুক্ত হত <unk>
স্টাফেন চেজেলাস

1
@ রাইমা, হ্যাঁ এটি আরও অনেক বেশি জড়িত সমাধান হতে পারে। এখানে এটা একটা সহজ পদ্ধতি যা শুধুমাত্র অত্যন্ত সম্ভাব্য (অভিমানী এর <unk>ঘটনার করছে পর্যন্ত appart, যদি না, ব্যবহার $/ = ">"এবং s/<unk>\z/<raw_unk>/g) সঠিক হচ্ছে।
স্টাফেন চেজেলাস

5

এখানে একটি ছোট গো প্রোগ্রাম যা কার্য সম্পাদন করে ( unk.go):

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

func main() {
    const (
        pattern     = "<unk>"
        replacement = "<raw_unk>"
    )
    var match int
    var char rune
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Split(bufio.ScanRunes)
    for scanner.Scan() {
        char = rune(scanner.Text()[0])
        if char == []rune(pattern)[match] {
            match++
            if match == len(pattern) {
                fmt.Print(replacement)
                match = 0
            }
        } else {
            if match > 0 {
                fmt.Print(string(pattern[:match]))
                match = 0
            }
            if char == rune(pattern[0]) {
                match = 1
            } else {
                fmt.Print(string(char))
            }
        }
    }
    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}

শুধু সঙ্গে এটি নির্মাণ go build unk.goএবং এটি চালানোর ./unk <input >output

সম্পাদনা করুন:

দুঃখিত, আমি পড়িনি যে সবকিছু এক লাইনে আছে, তাই আমি এখন ফাইল চরিত্রটি অক্ষর অনুসারে পড়ার চেষ্টা করেছি।

দ্বিতীয় সম্পাদনা:

সি প্রোগ্রাম হিসাবে একই ঠিক প্রয়োগ করা।


1
এটি কি পুরো ফাইলটিকে মেমরিতে পড়তে এড়াতে পারে?
বিড়াল

1
এটি ফাইলের অক্ষর অক্ষর অনুসারে পড়ে এবং পুরো ফাইলটিকে মেমরির মধ্যে ধারণ করে না , কেবল পৃথক অক্ষর।
প্যাট্রিক বুচার 19

1
scanner.Split(bufio.ScanRunes)যাদু করে
প্যাট্রিক বুচার 19

go doc bufio.MaxScanTokenSizeডিফল্ট বাফার আকারের জন্যও পরীক্ষা করে দেখুন ।
প্যাট্রিক বুচার

আপনার Cপ্রোগ্রামের মতো এটি আয়ারডওয়ার্ককে জেব্রার সাথে আয়ারডওয়ার্কের ইনপুট দিয়ে প্রতিস্থাপনের জন্য কাজ করে না।
আইক্রাস

1

এটি একটি 70 গিগাবাইট ফাইল এবং সাধারণ অনুসন্ধান এবং প্রতিস্থাপনের জন্য ওভারকিল হতে পারে, তবে হ্যাডোপ ম্যাপ্রেইডুস ফ্রেমওয়ার্কটি এখনই আপনার সমস্যাটি বিনা ব্যয়ে সমাধান করবে (স্থানীয়ভাবে এটি চালনার জন্য সেটআপ করার সময় 'সিঙ্গল নোড' বিকল্পটি চয়ন করুন) - এবং হতে পারে আপনার কোডটি সংশোধন করার প্রয়োজন ছাড়াই ভবিষ্যতে অসীম ক্ষমতাকে স্কেল করা হয়েছে।

Https://hadoop.apache.org/docs/stable/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html জাভা ব্যবহারের টিউটোরিয়াল (খুব সহজ) জাভা কিন্তু আপনি পার্ল বা ক্লায়েন্ট লাইব্রেরি পেতে পারেন আপনি যে ভাষা ব্যবহার করে মনে করেন।

সুতরাং যদি পরে আপনি যদি জানতে পারেন যে আপনি 7000 গিগাবাইট টেক্সট ফাইলগুলিতে আরও জটিল ক্রিয়াকলাপ করছেন - এবং এটি প্রতিদিন 100 বার করতে হচ্ছে - আপনি আপনার সরবরাহ করেছেন এমন একাধিক নোডে বা ভার্চুয়াল দ্বারা স্বয়ংক্রিয়ভাবে সরবরাহ করা কাজের ভার চাপ বিতরণ করতে পারেন- ভিত্তিক হাডোপ ক্লাস্টার


1
হ্যাঁ হ্যাঁ এটাই. "হ্যাডোপ ব্যবহার করবেন না - আপনার ডেটা এত বড় নয়" । এটি একটি খুব সাধারণ স্ট্রিমিং আইও সমস্যা।
উত্সবেদী

0

পূর্ববর্তী সমস্ত পরামর্শের জন্য পুরো ফাইলটি পড়া এবং পুরো ফাইলটি লেখা দরকার। এটি কেবল দীর্ঘ সময় নেয় না তবে এটির জন্য 70 গিগাবাইট খালি স্থান প্রয়োজন।

1) আমি যদি আপনাকে নির্দিষ্ট কেসটি সঠিকভাবে বুঝতে পারি তবে এটি কি একই অংশের দৈর্ঘ্যের অন্যান্য স্ট্রিং <<<< প্রতিস্থাপনযোগ্য হবে?

2 ক) একাধিক ঘটনা আছে? 2 খ) যদি হয় তবে আপনি কতজন জানেন?

আমি নিশ্চিত যে আপনি ইতিমধ্যে এই বছরের প্লাস সমস্যার সমাধান করেছেন এবং আমি জানতে চাই আপনি কী সমাধান ব্যবহার করেছেন।

আমি একটি সমাধান প্রস্তাব করলাম (সম্ভবত সি তে) সম্ভাব্য ব্লক ক্রসিং অ্যাকাউন্টে নেওয়া স্ট্রিংয়ের জন্য প্রতিটি ফাইল অনুসন্ধান করে যে ব্লকগুলি পড়বে। একবার একই স্টেমে একই দৈর্ঘ্যের বিকল্প এবং লেখার জন্য কেবল সেই ব্লকটি পাওয়া যাবে that ঘটনাগুলির জ্ঞাত সংখ্যা বা ফাইলের শেষ অবধি অবিরত। এর জন্য সংখ্যার ঘটনা যত কম লিখেছে এবং সর্বাধিক দ্বিগুণ হবে (যদি প্রতিটি ঘটনা 2 ব্লকের মধ্যে বিভক্ত হয়)। এর জন্য অতিরিক্ত কোনও স্থানের দরকার পড়বে না!


-1

যদি আমাদের সর্বনিম্ন পরিমাণ থাকে <unk>(জিপফের আইন দ্বারা প্রত্যাশিত),

awk -v RS="<unk>" -v ORS="<raw_unk>" 1

1
না sed। নির্বিশেষে স্মৃতিতে একবারে একটি লাইন পড়ে। এটি এই লাইনে ফিট করতে সক্ষম হবে না।
কুসালানন্দ

1
এই পতাকা ব্যবহার করার সময় জিএনইউ sedইনপুট / আউটপুট বাফারিং করবে না এমন কোনও ডকুমেন্টেশন আমি পাই না । আমি দেখতে পাচ্ছি না যে এটি আংশিক লাইনগুলি পড়বে।
কুসালানন্দ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.