আমার একটি ফাইল রয়েছে f1
:
line1
line2
line3
line4
..
..
আমি অন্য ফাইলটিতে থাকা সমস্ত লাইন মুছতে চাই f2
:
line2
line8
..
..
আমি সঙ্গে কিছু চেষ্টা cat
এবং sed
, যা ছিল না এমনকি আমি কি উদ্দেশ্যে পাসে। কিভাবে আমি এটি করতে পারব?
আমার একটি ফাইল রয়েছে f1
:
line1
line2
line3
line4
..
..
আমি অন্য ফাইলটিতে থাকা সমস্ত লাইন মুছতে চাই f2
:
line2
line8
..
..
আমি সঙ্গে কিছু চেষ্টা cat
এবং sed
, যা ছিল না এমনকি আমি কি উদ্দেশ্যে পাসে। কিভাবে আমি এটি করতে পারব?
উত্তর:
grep -v -x -f f2 f1
কৌতুক করা উচিত।
ব্যাখ্যা:
-v
মেলানো লাইনগুলি নির্বাচন করতে-x
শুধুমাত্র পুরো লাইন মেলে-f f2
থেকে নিদর্শন পেতে f2
এক পরিবর্তে ব্যবহার করতে পারেন grep -F
বা fgrep
মেলে সংশোধন স্ট্রিং থেকে f2
বদলে নিদর্শন (যদি আপনি বরং এ লাইন চিকিত্সা চেয়ে একটি "তুমি কি দেখতে হলে কি আপনি পেতে" পদ্ধতিতে লাইন অপসারণ চান f2
Regex নিদর্শন হিসাবে)।
grep
। f2
অনুসন্ধানটি শুরুর আগে যদি এটি সঠিকভাবে প্রাক-প্রক্রিয়াজাত করে তবে অনুসন্ধানে কেবল ও (এন) সময় লাগবে।
পরিবর্তে কম চেষ্টা করুন (ধরে নেওয়া f1 এবং f2 "ইতিমধ্যে সাজানো")
comm -2 -3 f1 f2
comm
যে সমাধানটির প্রশ্নের প্রশ্নটি ইঙ্গিত করে না যে রেখাগুলি f1
যেগুলি সাজানো হয়েছে তা ব্যবহারের পূর্বশর্তcomm
comm -2 -3 <(sort f1) <(sort f2)
অতিরিক্ত ফাইল নয় এমন ফাইলগুলি বাদ দেওয়ার জন্য আপনি AWK এর এসোসিয়েটিভ অ্যারে ব্যবহার করতে পারেন।
awk 'NR == FNR { list[tolower($0)]=1; next } { if (! list[tolower($0)]) print }' exclude-these.txt from-this.txt
আউটপুট "ক্রমে-টেক্সট" ফাইলের মতো একই ক্রমে থাকবে। tolower()
যদি আপনি যে প্রয়োজন ফাংশন, এটা কেস-অবশ করে তোলে।
অ্যালগরিদমিক জটিলতা সম্ভবত ও (এন) (বাদ-এই.txt আকার) + ও (এন) (এই-টেক্সট আকার থেকে) হবে
exclude-these.txt
খালি থাকলে এটি ব্যর্থ হয় (অর্থাত্ কোনও আউটপুট উত্পাদন করে না) । @ জোনা-ক্রিস্টোফার-সাহ্নওয়াল্টের উত্তর নীচে এই ক্ষেত্রে কাজ করে। আপনি একাধিক ফাইলও নির্দিষ্ট করতে পারেন যেমনawk '{if (f==1) { r[$0] } else if (! ($0 in r)) { print $0 } } ' f=1 done.out failed.out f=2 all-files.out
ডেনিস উইলিয়ামসনের উত্তরের মতো (বেশিরভাগ সিন্ট্যাকটিক পরিবর্তন, উদাহরণস্বরূপ কৌশলটির পরিবর্তে ফাইল নম্বর সেট করা NR == FNR
):
awk '{if (f==1) { r[$0] } else if (! ($0 in r)) { print $0 } } ' f=1 exclude-these.txt f=2 from-this.txt
অ্যাক্সেস r[$0]
সেই লাইনের জন্য এন্ট্রি তৈরি করে, কোনও মান সেট করার দরকার নেই।
ধরে নেওয়া যায় যে ধ্রুবক ধ্রুবক অনুসন্ধান এবং (গড়) ধ্রুবক আপডেটের সময় সহ একটি হ্যাশ টেবিল ব্যবহার করে, এর সময় জটিলতা হবে ও (এন + এম), যেখানে এন এবং এম ফাইলগুলির দৈর্ঘ্য। আমার ক্ষেত্রে, এনটি ছিল 25 মিলিয়ন ডলার এবং এম ~ 14000। অজানা সমাধানটি বাছাইয়ের চেয়ে অনেক দ্রুত ছিল এবং আমিও মূল ক্রমটি রাখা পছন্দ করি।
f
পরিষ্কার দেখতে পাই NR == FNR
, তবে এটি স্বাদের বিষয়। হ্যাশটিতে নিয়োগ এত দ্রুত হওয়া উচিত যে দুটি সংস্করণের মধ্যে পরিমাপযোগ্য গতির পার্থক্য নেই। আমি মনে করি জটিলতায় আমি ভুল ছিলাম - যদি অনুসন্ধানটি স্থির থাকে তবে আপডেটটিও ধ্রুব হওয়া উচিত (গড়)। আমি জানি না কেন আমি আপডেট লোগারিদমিক হবে বলে মনে করি। আমি আমার উত্তর সম্পাদনা করব।
awk '{if (f==1) { r[$0] } else if (! ($0 in r)) { print $0 } } ' f=1 empty.file done.out failed.out f=2 all-files.out
। অন্য awk
সমাধানটি খালি বাদ দেওয়া ফাইলের সাথে ব্যর্থ হয় এবং কেবলমাত্র একটি নিতে পারে।
আপনার যদি রুবি থাকে (1.9+)
#!/usr/bin/env ruby
b=File.read("file2").split
open("file1").each do |x|
x.chomp!
puts x if !b.include?(x)
end
যার ও (এন ^ 2) জটিলতা রয়েছে। আপনি যদি পারফরম্যান্স সম্পর্কে যত্ন নিতে চান তবে এখানে অন্য সংস্করণ
b=File.read("file2").split
a=File.read("file1").split
(a-b).each {|x| puts x}
বিয়োগফলকে প্রভাবিত করতে হ্যাশ ব্যবহার করে, তাই জটিলতা O (n) (a এর আকার) + O (n) (খের আকার)
এখানে একটি সামান্য বেঞ্চমার্ক, ব্যবহারকারীর সৌজন্যে 687687575,, তবে উপরের 100 ক লাইন সহ:
$ for i in $(seq 1 100000); do echo "$i"; done|sort --random-sort > file1
$ for i in $(seq 1 2 100000); do echo "$i"; done|sort --random-sort > file2
$ time ruby test.rb > ruby.test
real 0m0.639s
user 0m0.554s
sys 0m0.021s
$time sort file1 file2|uniq -u > sort.test
real 0m2.311s
user 0m1.959s
sys 0m0.040s
$ diff <(sort -n ruby.test) <(sort -n sort.test)
$
diff
উত্পন্ন 2 টি ফাইলের মধ্যে কোনও পার্থক্য নেই তা দেখানোর জন্য ব্যবহার করা হয়েছিল।
অন্যান্য বিভিন্ন উত্তরের মধ্যে কিছু সময় নির্ধারণের তুলনা:
$ for n in {1..10000}; do echo $RANDOM; done > f1
$ for n in {1..10000}; do echo $RANDOM; done > f2
$ time comm -23 <(sort f1) <(sort f2) > /dev/null
real 0m0.019s
user 0m0.023s
sys 0m0.012s
$ time ruby -e 'puts File.readlines("f1") - File.readlines("f2")' > /dev/null
real 0m0.026s
user 0m0.018s
sys 0m0.007s
$ time grep -xvf f2 f1 > /dev/null
real 0m43.197s
user 0m43.155s
sys 0m0.040s
sort f1 f2 | uniq -u
এমনকি একটি প্রতিসম পার্থক্যও নয়, কারণ এটি উভয় ফাইলে একাধিকবার প্রদর্শিত লাইনগুলি সরিয়ে দেয় s
কম স্ট্যান্ডিন এবং এখানে স্ট্রিংয়ের সাহায্যে ব্যবহার করা যেতে পারে:
echo $'a\nb' | comm -23 <(sort) <(sort <<< $'c\nb') # a
এসকিউএলাইট শেলের জন্য উপযুক্ত কাজ বলে মনে হচ্ছে:
create table file1(line text);
create index if1 on file1(line ASC);
create table file2(line text);
create index if2 on file2(line ASC);
-- comment: if you have | in your files then specify “ .separator ××any_improbable_string×× ”
.import 'file1.txt' file1
.import 'file2.txt' file2
.output result.txt
select * from file2 where line not in (select line from file1);
.q
কোনও 'প্রোগ্রামিং' উত্তর নয় তবে এখানে একটি দ্রুত এবং নোংরা সমাধান রয়েছে: কেবলমাত্র http://www.listdiff.com/compare-2-lists-differences-tool এ যান ।
স্পষ্টতই বিশাল ফাইলগুলির জন্য কাজ করবে না তবে এটি আমার জন্য কৌশলটি করেছে। কয়েকটি নোট: