আমি কীভাবে কোনও ফাইলের বিষয়বস্তু n বার বার বলতে পারি?


19

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

পরীক্ষাগুলি কেবল পুনরাবৃত্তি করার পরিবর্তে আমি বহুবার ইনপুট ডেটা ডুপ্লিকেট করতে চাই (উদাহরণস্বরূপ 1000) সুতরাং একটি 3 লাইন ফাইল 3000 লাইনে পরিণত হয় এবং আমি আরও অনেক পরিপূর্ণ পরীক্ষা চালাতে পারি।

আমি একটি ফাইলের মাধ্যমে ইনপুট ডেটাটি পাস করছি:

mycommand input-data.txt

উত্তর:


21

আপনি প্রয়োজন হবে না input-duplicated.txt

চেষ্টা করুন:

mycommand <(perl -0777pe '$_=$_ x 1000' input-data.txt)

ব্যাখ্যা

  • 0777: -0সেট ইনপুট রেকর্ড বিভাজক সেট করে (পার্ল বিশেষ ভেরিয়েবল $/যা ডিফল্টরূপে একটি নতুন লাইন)। এর চেয়ে বড় একটি মান সেট করা 0400পার্লকে পুরো ইনপুট ফাইলকে মেমরিতে স্লাপ করে।
  • pe: এর -pঅর্থ "এর দ্বারা প্রদত্ত স্ক্রিপ্ট প্রয়োগের পরে প্রতিটি ইনপুট লাইন মুদ্রণ করুন -e"।
  • $_=$_ x 1000: $_বর্তমান ইনপুট লাইন। যেহেতু আমরা একবারে পুরো ফাইলটি পড়ছি -0700, এর অর্থ সম্পূর্ণ ফাইল। x 1000সমগ্র ফাইলের 1000 কপি ছাপা হচ্ছে হবে।

খুশী হলাম। এটি নির্বোধ-দ্রুত। 1000 xargs এর জন্য 0.785s, এর জন্য 0.006s, সুতরাং হ্যাঁ, সম্ভবত আমি অন্যান্য লুপগুলির সাথে দেখছিলাম ওভারহেডের সমস্যাগুলি পরাস্ত করে।
অলি

এবং এটিকে 100000 বার বাম্পিং কেবল রানটাইমকে .002 দ্বারা বৃদ্ধি করে। এটা বেশ আশ্চর্যজনক।
অলি

@ অলি: ছোট ফাইলগুলির সাথে এবং আপনার যথেষ্ট স্মৃতি রয়েছে, perlএটি এত দক্ষ, এটি এটির জন্য ডিজাইন করা হয়েছে।
cuonglm

11

আমি প্রাথমিকভাবে ভাবছিলাম যে আমাকে একটি মাধ্যমিক ফাইল তৈরি করতে হবে তবে আমি কেবল আসল ফাইলটি ব্যাশের মধ্যে লুপ করতে পারি এবং এটি একটি ফাইল হিসাবে উপস্থিত হওয়ার জন্য কিছু পুনর্নির্দেশ ব্যবহার করতে পারি।

লুপটি করার সম্ভবত এক ডজন বিভিন্ন উপায় রয়েছে তবে এখানে চারটি রয়েছে:

mycommand <( seq 1000 | xargs -i -- cat input-data.txt )
mycommand <( for _ in {1..1000}; do cat input-data.txt; done )
mycommand <((for _ in {1..1000}; do echo input-data.txt; done) | xargs cat )
mycommand <(awk '{for(i=0; i<1000; i++)print}' input-data.txt)  #*

তৃতীয় পদ্ধতিটি নীচে মারুর মন্তব্য থেকে উন্নত এবং বিড়ালের জন্য ইনপুট ফাইলের একটি বড় তালিকা তৈরি করে। xargsসিস্টেম যতটা অনুমতি দেবে এটিকে এটিকে আর্গুমেন্টে বিভক্ত করবে। এটি এন পৃথক বিড়ালের তুলনায় অনেক দ্রুত ।

awkউপায় (দ্বারা অনুপ্রাণিত terdon এর উত্তর ) সম্ভবত সবচেয়ে অপ্টিমাইজ করা হয় কিন্তু এটি একটি সময়ে প্রতিটি লাইনে সদৃশ। এটি কোনও নির্দিষ্ট অ্যাপ্লিকেশন অনুসারে বা নাও পারে, তবে এটি দ্রুত এবং দক্ষতার দ্বারা বজ্রপাত হয়।


তবে এটি উড়ে তৈরি হচ্ছে। কিছু পড়ার চেয়ে বাশ আউটপুটিং খুব ধীর হতে পারে তাই আপনার পরীক্ষার জন্য একটি নতুন ফাইল তৈরি করা উচিত। ধন্যবাদ এটি কেবল একটি খুব সাধারণ এক্সটেনশন:

(for _ in {1..1000}; do echo input-data.txt; done) | xargs cat > input-duplicated.txt
mycommand input-duplicated.txt

3
আপনার উভয় কমান্ড বিড়াল এন বার চলমান আছে। একবার বিড়াল চালানো এবং এটিকে একটি যুক্তি N বার খাওয়ানো কি আরও দক্ষ হবে না? কিছু একটা cat $(for i in {1..N}; do echo filename; done)। এতে আরগ আকারের সীমাবদ্ধতা রয়েছে তবে দ্রুত হওয়া উচিত।
মারু

@ মুরু ভাল ধারণা। কিছু কাজ দরকার কিন্তু আমি এটি যুক্ত করব। বর্তমান বাস্তবায়ন ~ 0.020 এর মধ্যে একটি 7-লাইন ফাইলের 1000 পুনরাবৃত্তি করছে। এটি আমার সংস্করণগুলির চেয়ে সত্যিই অনেক ভাল, তবে জ্নুকের পার্ল স্তরে নয়।
অলি

6

এখানে একটি awkসমাধান:

awk '{a[NR]=$0}END{for (i=0; i<1000; i++){for(k in a){print a[k]}}}' file 

এটি মূলত @ জ্নুকের পার্লের মতো দ্রুত (আমি দু'বার 1000 দৌড়েছি এবং গড় সময় পেয়েছি):

$ for i in {1..1000}; do 
 (time awk '{a[NR]=$0}END{for (i=0;i<1000;i++){for(k in a){print a[k]}}}' file > a) 2>&1 | 
    grep -oP 'real.*?m\K[\d\.]+'; done | awk '{k+=$1}END{print k/1000}'; 
0.00426

$ for i in {1..1000}; do 
  (time perl -0777pe '$_=$_ x 1000' file > a ) 2>&1 | 
    grep -oP 'real.*?m\K[\d\.]+'; done | awk '{k+=$1}END{print k/1000}'; 
0.004076

1
ন্যায্যতায় আপনি সম্ভবত awk '{for(i=0; i<1000; i++)print}' input-data.txtএটিকে সহজতর করতে পারেন তাই এটি একবারে প্রতিটি লাইনের 1000 কপি সরবরাহ করে। সমস্ত অনুষ্ঠানে উপযুক্ত হবে না তবে আরও দ্রুত, কম বিলম্ব এবং পুরো ফাইলটি র‌্যামে ধারণ করার দরকার নেই।
অলি

@ অলি, আমি ধরেছিলাম যে আপনি লাইন অর্ডার রাখতে চেয়েছিলেন যাতে এটি ঠিক 123123123ছিল তবে তা 111222333ছিল না। আপনার সংস্করণ জ্নুকের তুলনায় স্পষ্টতই দ্রুত, এটির গড় গড় 0.00297 সেকেন্ড। সম্পাদনা: স্ক্র্যাচ করুন যে, আমি একটি ভুল করেছি, এটি আসলে 0.004013 সেকেন্ডের সমান।
টেরডন

5

আমি কেবল একটি পাঠ্য সম্পাদক ব্যবহার করব।

vi input-data.txt
gg (move cursor to the beginning of the file)
yG (yank til the end of the file)
G (move the cursor to the last line of the file)
999p (paste the yanked text 999 times)
:wq (save the file and exit)

আপনার যদি একেবারে কমান্ড-লাইনের মাধ্যমে এটি করার দরকার হয় (এটির জন্য আপনার কমান্ডটি vimইনস্টল করা viদরকার :normal), আপনি এটি ব্যবহার করতে পারেন:

vim -es -u NONE "+normal ggyGG999p" +wq input-data.txt

এখানে -es(বা -e -s) -u NONEভিমটি নিঃশব্দরূপে পরিচালিত করে, সুতরাং এটি আপনার টার্মিনাল উইন্ডোটি ধরে নেওয়া উচিত নয় এবং এটি আপনার ভিআরসিআরটির দিকে নজর দেওয়া থেকে বিরত রাখে, এটি অন্যথায় এটির চেয়ে কিছুটা দ্রুত চালানো উচিত (সম্ভবত আপনি আরও যদি দ্রুত ব্যবহার করেন তবে ভিম প্লাগইন অনেক)।


হ্যাঁ, তবে এটি সমস্ত ম্যানুয়াল যা এটিকে অন্যান্য দ্রষ্টব্যগুলির তুলনায় ধীরে ধীরে বিস্তারের বেশ কয়েকটি ক্রমকে আরও জটিল করে তোলে।
টেরডন

4

এখানে একটি সাধারণ ওয়ান-লাইনার, কোনও স্ক্রিপ্টিং জড়িত নেই:

mycommand <(cat `yes input-data.txt | head -1000 | paste -s`)

ব্যাখ্যা

  • `yes input-data.txt | head -1000 | paste -s`input-data.txtসাদা স্থান দ্বারা পৃথক করা 1000 বার পাঠ্য উত্পাদন করে
  • তারপরে পাঠ্য catফাইলের তালিকা হিসাবে প্রেরণ করা হবে

এই সমাধানটি কাজ করছে বলে মনে হচ্ছে না। আপনার কি দরকার xargs paste -s? এটি কাজ করে তবে ইনপুট ফাইলে নতুন লাইন সংরক্ষণ করে না।
জেরেমিকুন

আপনি সঠিক অ্যাডাস্ট্রোফ ব্যবহার করছেন তা নিশ্চিত করুন।
রোব

2

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

#!/usr/bin/env python3
from __future__ import print_function
import sys,os

def error_out(string):
    sys.stderr.write(string+"\n")
    sys.exit(1)

def read_bytewise(fp):
    data = fp.read(1024)
    print(data.decode(),end="",flush=True)
    while data:
        data = fp.read(1024)
        print(data.decode(),end="",flush=True)
    #fp.seek(0,1)

def main():
    howmany = int(sys.argv[1]) + 1
    if not os.path.isfile(sys.argv[2]):
       error_out("Needs a valid file") 

    fp = open(sys.argv[2],'rb')
    for i in range(1,howmany):
        #print(i)
        fp.seek(0)
        read_bytewise(fp)
    fp.close()

if __name__ == '__main__': main()

স্ক্রিপ্ট নিজেই ব্যবহারে বেশ সহজ:

./repeat_text.py <INT> <TEXT.txt>

3 লাইনের পাঠ্য ফাইল এবং 1000 পুনরাবৃত্তির জন্য এটি প্রায় 0.1 সেকেন্ডে বেশ ঠিক হয়ে যায়:

$ /usr/bin/time ./repeat_text.py 1000 input.txt  > /dev/null                                                             
0.10user 0.00system 0:00.23elapsed 45%CPU (0avgtext+0avgdata 9172maxresident)k
0inputs+0outputs (0major+1033minor)pagefaults 0swaps

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


1

আমরা কোনও অতিরিক্ত ফাইল বা বিশেষ প্রোগ্রামগুলি ছাড়াই এটি সমাধান করতে পারি, খাঁটি বাশ (ভাল, বিড়াল একটি স্ট্যান্ডার্ড কমান্ড)।

ব্যাশের অভ্যন্তরে প্রিন্টফের একটি বৈশিষ্ট্যের ভিত্তিতে আমরা একটি পুনরাবৃত্তি স্ট্রিং উত্পন্ন করতে পারি):

printf "test.file.txt %.0s\n" {1..1000}

তারপরে, আমরা 1000 ফাইলের নাম (পুনরাবৃত্তি) এবং কল ক্যাটকে এই জাতীয় তালিকা পাঠাতে পারি:

printf "test.file.txt %.0s" {1..1000} | xargs cat 

এবং পরিশেষে, আমরা নির্বাহ করতে কমান্ডকে আউটপুট দিতে পারি:

mycommand "$( printf "%.0sinput.txt\n" {1..1000} | xargs cat )"

অথবা, যদি কমান্ডটি স্টিডিনে ইনপুট গ্রহণ করতে হয়:

mycommand < <( printf "%.0sinput.txt\n" {1..1000} | xargs cat )

হ্যাঁ, দ্বিগুণ <প্রয়োজন।


0

আমি লুপের জন্য ইউনিক্স ব্যবহার করে একটি নতুন ফাইল তৈরি করব:

content=$(cat Alex.pgn); for i in {1..900000}; do echo "$content" >> new_file; done 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.