একটি প্যাটার্নে ফাইলটি দুটি ভাগে বিভক্ত করুন


14

কোনও ধরণে একটি বৃহত ফাইলকে কীভাবে দুটি ভাগে ভাগ করবেন?

একটি উদাহরণ দেওয়া file.txt:

ABC
EFG
XYZ
HIJ
KNL

আমি এই ফাইলটি XYZএমনভাবে বিভক্ত করতে চাই যাতে file1লাইন আপ-টু XYZএবং বাকী রেখাগুলি থাকে file2


করা উচিত XYZলাইন আউটপুট অথবা না অন্তর্ভুক্ত হবে?
টেরডন

@terdon আমার ক্ষেত্রে কোনও "XYZ" লাইন ফাইল 2 এর অংশ হওয়া উচিত নয়। তবে যদি আপনার এটি করার কোনও উপায় থাকে তবে দয়া করে উত্তর দিন। এটি অন্য কোনও ক্ষেত্রে কার্যকর হতে পারে।
d.putto

যথেষ্ট ভাল, সম্পন্ন।
টেরডন

উত্তর:


10

আপনি যা awkকরতে পারেন তা সহ:

awk '{print >out}; /XYZ/{out="file2"}' out=file1 largefile


ব্যাখ্যা: প্রথম awkআর্গুমেন্ট ( out=file1) ফাইলনামের সাথে একটি ভেরিয়েবল সংজ্ঞা দেয় যা পরবর্তী আর্গুমেন্ট ( largefile) প্রক্রিয়া করার সময় আউটপুট জন্য ব্যবহৃত হবে । awkপ্রোগ্রাম পরিবর্তনশীল দ্বারা নির্দিষ্ট ফাইলে সব লাইন প্রিন্ট হবে out( {print >out})। যদি প্যাটার্নটি XYZপাওয়া যায় তবে আউটপুট ভেরিয়েবলটি নতুন ফাইল ( {out="file2}") -এ চিহ্নিত করতে পুনরায় সংজ্ঞায়িত করা হবে যা পরবর্তী ডেটা লাইনগুলি মুদ্রণের জন্য লক্ষ্য হিসাবে ব্যবহৃত হবে।

তথ্যসূত্র:


14

এটি একটি কাজ csplit:

csplit -sf file -n 1 large_file /XYZ/

হবে silently ফাইল বিভক্ত, প্রাক দিয়ে তোমাকে টুকরা টুকরা তৈরি fIX fileএবং nএকটি একক অঙ্ক ব্যবহার umbered যেমন file0ইত্যাদি লক্ষ্য করুন ব্যবহার /regex/করার জন্য বিভক্ত হবে, কিন্তু যে ম্যাচ লাইন সহ না regex। আপ বিভক্ত করতে এবং লাইন ম্যাচিং সহ regexযোগ একটি +1অফসেট:

csplit -sf file -n 1 large_file /XYZ/+1

এটি দুটি ফাইল তৈরি করে file0এবং file1। আপনার যদি তাদের নামকরণের প্রয়োজন হয় file1এবং file2আপনি সর্বদা csplitকমান্ডটিতে একটি খালি প্যাটার্ন যুক্ত করতে পারেন এবং প্রথম ফাইলটি সরিয়ে ফেলতে পারেন:

csplit -sf file -n 1 large_file // /XYZ/+1

সৃষ্টি file0, file1এবং file2কিন্তু file0খালি যাতে আপনি নিরাপদে সরাতে পারেন:

rm -f file0

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

6

আধুনিক সহ kshএখানে উপরের ভিত্তিক উত্তরের একটি শেল বৈকল্পিক (অর্থাত্‍হীন sed) রয়েছে sed:

{ read in <##XYZ ; print "$in" ; cat >file2 ;} <largefile >file1


এবং kshএককভাবে আরও একটি বৈকল্পিক (অর্থাত্ বাদও দেওয়া cat):

{ read in <##XYZ ; print "$in" ; { read <##"" ;} >file2 ;} <largefile >file1


(খাঁটি kshসমাধানটি বেশ পারফরম্যান্স বলে মনে হচ্ছে; ২.৪ গিগাবাইট পরীক্ষার ফাইলে এটি প্রয়োজনে 19-21 সেকেন্ডের sed/ 39 catভিত্তিক পদ্ধতির সাথে 39-47 সেকেন্ডের তুলনায় )।


এটা খুব দ্রুত। তবে আমি মনে করি না যে আপনার দরকার readএবং print- আপনার এটি কেবল নিজের সমস্ত আউটপুটে যেতে দেওয়া উচিত। যদি আপনি সম্পূর্ণ এএসটি টুলকিটটি তৈরি করেন এবং kshবিল্টিনগুলি সমস্তই সংকলন করেন তবে পারফরম্যান্স আরও ভাল হয় - এটি আমার কাছে অদ্ভুত যে sedআসলে তাদের মধ্যে নয়। তবে while <file doআমার মত ধরণের স্টাফ দিয়ে আপনার sedএতটা প্রয়োজন হবে না ...
মাইকসার্ভ 10:55

যদিও আমি কৌতূহলী - কীভাবে awkআপনার মানদণ্ডে পারফর্ম করলেন ? এবং যদিও আমি নিশ্চিত kshযে সম্ভবত এই লড়াইটি সবসময়ই জিতবে, আপনি যদি কোনও জিএনইউ ব্যবহার করেন তবে আপনার sedপক্ষে খুব বেশি ন্যায্য নয় sed- -uজিএনইউ'র এনবার্ফার্ড পজিক্সলির কাছে একটি প্রস্রাব-দরিদ্র পদ্ধতির বিষয়টি নিশ্চিত করে যেখানে প্রোগ্রামটি বন্ধ হয়ে যায় সেখানে বর্ণনাকারীর অফসেটটি বাকী থাকে uring এটি - প্রোগ্রামটির নিয়মিত অপারেশনটি ধীর করার দরকার নেই - বাফারিং ঠিক আছে - সব sedশেষ করার পরে বিবরণীর সন্ধান করতে হবে। জিএনইউ যে কারণেই হোক না কেন সেই মানসিকতাটিকে বিপরীত করে।
মাইকজার্ভ

@mikeserv; পুনঃনির্দেশ প্যাটার্ন ম্যাচটি প্যাটার্নটি পাওয়া না হওয়া পর্যন্ত সম্পন্ন করা হয় এবং স্পষ্টভাবে চিত্রিত হিসাবে না করা হলে পাওয়া প্যাটার্ন সহ লাইনটি মুদ্রণ করা হবে না। (কমপক্ষে এটি আমার পরীক্ষা দেখিয়েছিল।) নোট করুন যে এখানে নেই while; মুদ্রণ স্পষ্টভাবে <##পুনঃনির্দেশ অপারেটরের সংজ্ঞাযুক্ত পার্শ্ব প্রতিক্রিয়া হিসাবে সম্পন্ন করা হয় । এবং শুধুমাত্র ম্যাচিং লাইনের মুদ্রণ প্রয়োজন। (এইভাবে শেল বৈশিষ্ট্য বাস্তবায়ন Incl./excl এর সমর্থনের জন্য সবচেয়ে নমনীয়)) whileআমি একটি স্পষ্ট লুপটি উল্লেখযোগ্যভাবে ধীর হতে আশা করব (তবে পরীক্ষা করে দেখিনি) have
জ্যানিস

1
@mikeserv; আহ ঠিক আছে. বিটিডাব্লু, আমি কেবল এর headপরিবর্তে চেষ্টা করেছি read; এটি শুধুমাত্র একটি সামান্য বিট ধীর বলে মনে হয়, কিন্তু এটি terser কোডের: { head -1 <##XYZ ; { read <##"" ;} >file4 ;} <largefile >file3
জেনিস

1
@mikeserv; ভাল যুক্তি; এটা ছিল না। তবে আমি যখন বিল্টিনটি সক্রিয় করি (সবেমাত্র সম্পন্ন হয়ে ফলাফলগুলি পরীক্ষা করে দেখি) এটি একই সংখ্যা, আশ্চর্যের বিষয়। (পড়ার সাথে তুলনায় কিছু ফাংশন কল ওভারহেড হতে পারে?)
জ্যানিস

6
{ sed '/XYZ/q' >file1; cat >file2; } <infile

GNU এর সাথে sedআপনার -unbuffered সুইচটি ব্যবহার করা উচিত । বেশিরভাগ অন্যান্যদের sedশুধু কাজ করা উচিত।

এক্সওয়াইজেড ছেড়ে যাওয়ার জন্য ...

{ sed -n '/XYZ/q;p'; cat >file2; } <infile >file1

3

জিএনইউ সেড দিয়ে এটি ব্যবহার করে দেখুন:

sed -n -e '1,/XYZ/w file1' -e '/XYZ/,${/XYZ/d;w file2' -e '}' large_file

সংক্ষিপ্ত:sed -e '1,/XYZ/{w file1' -e 'd}' large_file > file2
don_crissti

1

টার্গেটের প্যাটার্নটি মিলেছে কিনা তার উপর নির্ভর করে একটি সহজ হ্যাক হয় STDOUT বা STDERR এ মুদ্রণ করা। তারপরে আপনি শেলটির পুনর্নির্দেশ অপারেটরগুলি সেই অনুযায়ী আউটপুটটিকে পুনর্নির্দেশ করতে ব্যবহার করতে পারেন । উদাহরণস্বরূপ, পার্ল ধরে, ইনপুট ফাইল ডাকা fএবং দুটি আউটপুট ফাইল f1এবং f2:

  1. বিভাজন প্যাটার্নের সাথে মেলে এমন লাইনটি বাতিল করা:

    perl -ne 'if(/XYZ/){$a=1; next} ; $a==1 ? print STDERR : print STDOUT;' f >f1 2>f2
  2. ম্যাচ করা লাইন সহ:

    perl -ne '$a=1 if /XYZ/; $a==1 ? print STDERR : print STDOUT;' f >f1 2>f2

বিকল্পভাবে, বিভিন্ন ফাইল হ্যান্ডলগুলিতে মুদ্রণ করুন:

  1. বিভাজন প্যাটার্নের সাথে মেলে এমন লাইনটি বাতিল করা:

    perl -ne 'BEGIN{open($fh1,">","f1");open($fh2,">","f2");}
    if(/XYZ/){$a=1; next}$a==1 ? print $fh1 "$_" : print $fh2 "$_";' f
    
  2. ম্যাচ করা লাইন সহ:

    perl -ne 'BEGIN{open($fh1,">","f1"); open($fh2,">","f2");}
              $a=1 if /XYZ/; $a==1 ? print $fh1 "$_" : print $fh2 "$_";' f
    
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.