দুটি ফাইলের মধ্যে লাইনগুলি সন্ধান করার জন্য ইউনিক্স কমান্ড


178

আমি নিশ্চিত যে আমি একবার ইউনিক্স কমান্ড পেয়েছি যা দুটি বা আরও বেশি ফাইল থেকে সাধারণ লাইনগুলি মুদ্রণ করতে পারে, কেউ কি এর নাম জানেন? এটা তুলনায় অনেক সহজ ছিল diff


5
এই প্রশ্নের উত্তর অগত্যা সকলেই যা চাইবে তা নয়, যেহেতু commবাছাই করা ইনপুট ফাইলগুলির প্রয়োজন। আপনি যদি কেবল লাইন বাই লাইন সাধারণ দেখতে চান তবে এটি দুর্দান্ত। তবে আপনি যদি চান যা আমি "অ্যান্টি-ডিফ" commবলব , কাজটি করবেন না।
রবার্ট পি। গোল্ডম্যান

@ রবার্টপি.ল্ডম্যান দুটি ফাইলের মধ্যে সাধারণ হওয়ার উপায় আছে যখন ফাইল 1 এ আংশিক প্যাটার্ন pr-123-xy-45থাকে এবং ফাইল 2 থাকে ec11_orop_pr-123-xy-45.gz। আমার ফাইল 3 থাকা দরকারec11_orop_pr-123-xy-45.gz
চন্দন চৌধুরী

পাঠ্য-ফাইলগুলি লাইন-বাই-লাইনে বাছাই করার জন্য এটি দেখুন
y2k-shubham

উত্তর:


216

আপনি যে আদেশটি সন্ধান করছেন তা হ'ল comm। উদাহরণ: -

comm -12 1.sorted.txt 2.sorted.txt

এখানে:

-১ : কলাম 1 টি দমন করুন (1.sort.txt এর জন্য অনন্য লাইনগুলি)

-২ : কলাম 2 চাপুন (২.sort.txt এর জন্য অনন্য লাইনগুলি)


27
সাধারন ব্যবহার: কম -১২.২০.sort.txt ২.Sort.txt
ফেদির আরওয়াইএইচটিআইটিকি

45
কমের জন্য বাছাই করা ফাইলের দরকার পড়ে, উভয় ফাইলের সাধারণ লাইনগুলি পেতে আপনি গ্রিপ-ফাই ফাইল 1 ফাইল 2 নিতে পারেন।
ফেরি

2
@ আফেডি (আপনার উত্তরটি থেকে আমার মন্তব্যটি পুনরাবৃত্তি করা, কারণ আপনার মন্তব্যটি মূলত একটি পুনরাবৃত্ত উত্তর হিসাবে পোস্ট করা হয়েছে) grepএমন কিছু অদ্ভুত কাজ করে যা আপনি আশা করেন না। বিশেষত, এর মধ্যে সমস্ত কিছুই 1.txtএকটি নিয়মিত প্রকাশ হিসাবে ব্যাখ্যা করা হবে এবং একটি সরল স্ট্রিং নয়। এছাড়াও, যে কোনও ফাঁকা রেখাটি 1.txtসমস্ত লাইনের সাথে মেলে 2.txt। সুতরাং grepশুধুমাত্র খুব নির্দিষ্ট পরিস্থিতিতে কাজ করবে। আপনি কমপক্ষে fgrep(বা grep -f) ব্যবহার করতে চাইবেন তবে ফাঁকা-লাইন জিনিসটি সম্ভবত এই প্রক্রিয়াটির সর্বনাশ ঘটাতে চলেছে।
ক্রিস্টোফার শুল্টজ

11
দেখুন ferdy এর উত্তর নিচে এবং, ক্রিস্টোফার শুলজ এর এবং এটি আমার মন্তব্য। টিএল; ডিআর - ব্যবহার করুন grep -F -x -f file1 file2
জোনাথন লেফলার 14

1
@ বাপ্পার্স: কমান্ড থেকে আউটপুটটি কীভাবে comm3 টি পৃথক ফাইলে রূপান্তর করা যায় সে জন্য আমি একটি স্ব-উত্তরযুক্ত প্রশ্নোত্তর সরবরাহ করেছি উত্তরটি এখানে আরামে ফিট করার জন্য অনেক বড় ছিল।
জোনাথন লেফলার

61

সহজে প্রয়োগ করতে Comm কমান্ড পাঁচমিশালী ফাইল, ব্যাশ এর ব্যবহার প্রক্রিয়া প্রতিকল্পন :

$ bash --version
GNU bash, version 3.2.51(1)-release
Copyright (C) 2007 Free Software Foundation, Inc.
$ cat > abc
123
567
132
$ cat > def
132
777
321

সুতরাং abc এবং def ফাইলগুলির মধ্যে একটি লাইন মিল রয়েছে, এটি একটি "132" এর সাথে। অচলিত ফাইলগুলিতে কম ব্যবহার করা হচ্ছে:

$ comm abc def
123
    132
567
132
    777
    321
$ comm -12 abc def # No output! The common line is not found
$

শেষ লাইনটি কোনও আউটপুট দেয়নি, সাধারণ লাইনটি আবিষ্কার করা হয়নি।

Now ব্যবহার Comm প্রক্রিয়া প্রতিকল্পন ফাইল বাছাই সাজানো ফাইল:

$ comm <( sort abc ) <( sort def )
123
            132
    321
567
    777
$ comm -12 <( sort abc ) <( sort def )
132

এখন আমরা 132 লাইন পেয়েছি!


2
তাই ... sort abc > abc.sorted, sort dev > def.sortedএবং তারপর comm -12 abc.sorted def.sorted?
নিকানা রেকলাভিক্স

1
@ নিকানা রেকলাভিকস এবং তারপরে অস্থায়ী ফাইলগুলি পরে মুছে ফেলার কথা মনে রাখবেন এবং কোনও ত্রুটির ক্ষেত্রে পরিষ্কার করার সাথে লড়াই করুন। অনেক পরিস্থিতিতে, প্রক্রিয়া প্রতিস্থাপনটিও অনেক দ্রুত হবে কারণ আপনি ফলাফলগুলি মেমরির সাথে মাপসই করা যায় ততক্ষণ আপনি ডিস্ক I / O এড়াতে পারবেন।
ট্রিপল

29

পার্ল ওয়ান-লাইনার পরিপূরক করতে এখানে এর awkসমতুল্য:

awk 'NR==FNR{arr[$0];next} $0 in arr' file1 file2

এটি file1অ্যারে থেকে সমস্ত লাইন পড়বে arr[]এবং তারপরে প্রতিটি লাইনের জন্য file2এটি ইতিমধ্যে অ্যারে (যেমন file1) এর মধ্যে বিদ্যমান কিনা তা পরীক্ষা করে দেখবে । যে লাইনগুলি পাওয়া যায় সেগুলি সেগুলি ক্রমে প্রিন্ট করা হবে file2। নোট করুন যে তুলনাটি সূচী হিসাবে অ্যারেতে in arrসম্পূর্ণ লাইনটি ব্যবহার করে file2, সুতরাং এটি কেবলমাত্র পুরো লাইনে সঠিক মিলগুলির প্রতিবেদন করবে।


2
এটা সঠিক উত্তর. অন্য কারওওই সাধারণভাবে কাজ করা যায় না (আমি এগুলি চেষ্টা করি নি perl, কারণ)। এক মিলিয়ন ধন্যবাদ, মিসেস
এনটোনিও

1
সাধারণ লাইনগুলি প্রদর্শন করার সময় অর্ডার সংরক্ষণ করা কিছু ক্ষেত্রে সত্যিই কার্যকর হতে পারে যে কারণে কমটি বাদ দেয়।
tuxayo

1
যদি কোনও নির্দিষ্ট কলামের উপর ভিত্তি করে কেউ একই জিনিস করতে চায় তবে অবাস্তব জানে না, কেবল কলাম 5 এর উদাহরণ হিসাবে উদাহরণস্বরূপ both 5 এর সাথে উভয় $ 0 এর প্রতিস্থাপন করুন যাতে আপনি কলাম 5 এ একই শব্দের সাথে 2 টি ফাইলে ভাগ করে লাইন পান
ফাতেহসারিগল

24

আপনি বলতে চাইছেন comm?

বাছাই করা ফাইলগুলি FILE1 এবং FILE2 লাইন লাইন দিয়ে তুলনা করুন।

কোনও বিকল্প নেই, তিন-কলাম আউটপুট উত্পাদন। কলামের একটিতে FILE1 এর জন্য অনন্য লাইন রয়েছে, দুটি কলামে FILE2 এর জন্য অনন্য লাইন রয়েছে এবং তিনটি কলামে উভয় ফাইলের জন্য সাধারণ লাইন রয়েছে।

এই তথ্যগুলি সন্ধানের গোপন তথ্যগুলি পৃষ্ঠা। জিএনইউ প্রোগ্রামগুলির জন্য, তারা তাদের ম্যান-পৃষ্ঠাগুলির চেয়ে অনেক বেশি বিস্তারিত। চেষ্টা করুন info coreutilsএবং এটি আপনাকে সমস্ত ছোট দরকারী ব্যবহারের তালিকা দেবে।


19

যদিও

grep -v -f 1.txt 2.txt > 3.txt

আপনাকে দুটি ফাইলের পার্থক্য দেয় (যা 2.txt এ রয়েছে এবং 1.txt এ নয়) আপনি সহজেই একটি করতে পারেন

grep -f 1.txt 2.txt > 3.txt

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


2
grepএমন কিছু অদ্ভুত কাজ করে যা আপনি আশা করেন না। বিশেষত, এর মধ্যে সমস্ত কিছুই 1.txtএকটি নিয়মিত প্রকাশ হিসাবে ব্যাখ্যা করা হবে এবং একটি সরল স্ট্রিং নয়। এছাড়াও, যে কোনও ফাঁকা রেখাটি 1.txtসমস্ত লাইনের সাথে মেলে 2.txt। সুতরাং এটি কেবল খুব নির্দিষ্ট পরিস্থিতিতে কাজ করবে।
ক্রিস্টোফার শুল্টজ

13
@ ক্রিস্টোফারশাল্টজ: POSIX grepস্বরলিপিগুলি ব্যবহার করে এই উত্তরটি আরও ভালভাবে কাজ করার জন্য এটি আপগ্রেড করা সম্ভব , যা grepবেশিরভাগ আধুনিক ইউনিক্স ভেরিয়েন্টে প্রাপ্তদের দ্বারা সমর্থিত । নিয়মিত অভিব্যক্তি দমন -Fকরতে যোগ করুন (বা ব্যবহার করুন fgrep)। যোগ -x(সঠিক জন্য) শুধুমাত্র পুরো লাইন মেলে।
জোনাথন লেফলার 14

commবাছাই করা ফাইলগুলির জন্য কেন আমাদের নেওয়া উচিত ?
ইউলিস বিএন

2
@ ইউলিসিবিএন যতক্ষণ commনা বাছাই করা হয় ততক্ষণ ইচ্ছামত বড় ফাইলগুলির সাথে কাজ করতে পারে কারণ এটির জন্য কেবল মেমোরিতে তিনটি লাইন রাখা দরকার (আমি জিএনইউ অনুমান করছি commযে লাইনগুলি আসলে দীর্ঘ হলে কেবল একটি উপসর্গ রাখতে পারে)। grepসমাধান মেমরি সমস্ত অনুসন্ধান এক্সপ্রেশন রাখতে হবে।
ট্রিপল

8
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2

এই বেশী ভালো কাজ করছে commকমান্ড যেমন প্রতিটি লাইন অনুসন্ধান করে file1file2যেখানে commশুধুমাত্র তুলনা লাইন যদি হবে nমধ্যে file1হয় লাইন সমান nমধ্যে file2
তেরিহিহিনা

1
@teriiehina: না; commকেবল ফাইল 1-তে লাইন এন এর সাথে ফাইল 2-র লাইন এন এর সাথে তুলনা করে না। এটি পুরোপুরি ভালভাবে উভয় ফাইলের মধ্যে sertedোকানো লাইনগুলির পরিচালনা করতে পারে (যা অবশ্যই অন্য ফাইল থেকে লাইনগুলির একটি সিরিজ মুছার সমতুল্য)। এটির জন্য কেবল ইনপুটগুলি বাছাই করা দরকার।
জোনাথন লেফলার

commযদি কেউ অর্ডার রাখতে চান তবে উত্তরের চেয়ে ভাল । awkকেউ সদৃশ না চাইলে উত্তরের চেয়ে উত্তম ।
tuxayo

: একটি ব্যাখ্যা এখানে stackoverflow.com/questions/17552789/...
ক্রিস Koknat

8

দুটি ফাইল এখনও বাছাই না করা থাকলে আপনি ব্যবহার করতে পারেন:

comm -12 <(sort a.txt) <(sort b.txt)

এবং এটি কাজ করবে, comm: file 2 is not in sorted order যখন করার সময় ত্রুটি বার্তা এড়ানো comm -12 a.txt b.txt


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

আমি এই উত্তরটিও জনাথনলফলার দেখতে পাইনি কারণ এই অংশটি উত্তরের একেবারে শেষে ছিল, উত্তরের অন্যান্য উপাদানগুলির সাথে মিশ্রিত ছিল। অন্য উত্তরটি আরও সুনির্দিষ্ট হলেও আমার উপকারটি হ'ল যে আমি দ্রুত সমাধানের জন্য চাইছি তার কাছে পড়ার জন্য কেবল 2 টি লাইন থাকবে। কখনও কখনও আমরা বিশদ উত্তর খুঁজছি এবং কখনও কখনও আমরা তাড়াহুড়োয়াম এবং একটি দ্রুত-পড়ার জন্য প্রস্তুত টু-পেস্ট উত্তর ঠিক আছে is
বাসজ

এছাড়াও আমি ক্রেডিট / রেপ সম্পর্কে কোনও চিন্তা করি না, আমি এই উদ্দেশ্যে পোস্ট করি নি।
বাসজ

1
এছাড়াও লক্ষ করুন যে প্রক্রিয়া প্রতিস্থাপন সিনট্যাক্সটি <(command)পসিক্স শেলটিতে পোর্টেবল নয়, যদিও এটি বাশ এবং কিছু অন্যান্য ক্ষেত্রে কাজ করে।
ট্রিপল


3

লিনাক্সের সীমিত সংস্করণে (যেমন কিউএনএপি (নাস) আমি কাজ করছিলাম):

  • কম উপস্থিত ছিল না
  • grep -f file1 file2@ ক্রিস্টোফারশাল্টজ-এর কথা মতো কিছু সমস্যা সৃষ্টি করতে পারে এবং ব্যবহারটি grep -F -f file1 file2আসলেই ধীর ছিল ( ২০ মিনিটের বেশি - এটি শেষ হয়নি - ২০ এমবি-র উপরে ফাইলগুলিতে নীচের পদ্ধতিটি দিয়ে ২-৩ সেকেন্ডের বেশি)

সুতরাং আমি এখানে কি করেছি:

sort file1 > file1.sorted
sort file2 > file2.sorted

diff file1.sorted file2.sorted | grep "<" | sed 's/^< *//' > files.diff
diff file1.sorted files.diff | grep "<" | sed 's/^< *//' > files.same.sorted

যদি files.same.sortedফাইল 1 এর চেয়ে একই ক্রমের জন্য এই লাইনটি যুক্ত করার চেয়ে মূল লোকগুলির চেয়ে একই ক্রমে থাকত:

awk 'FNR==NR {a[$0]=$0; next}; $0 in a {print a[$0]}' files.same.sorted file1 > files.same

অথবা, ফাইলের চেয়ে একই আদেশের জন্য:

awk 'FNR==NR {a[$0]=$0; next}; $0 in a {print a[$0]}' files.same.sorted file2 > files.same

2

কেবলমাত্র রেফারেন্সের জন্য যদি কেউ এখনও একাধিক ফাইলের জন্য এটি কীভাবে করতে দেখছেন তবে অনেকগুলি ফাইল জুড়ে মিলের লাইনগুলি খুঁজে পাওয়ার লিঙ্কযুক্ত উত্তরটি দেখুন


এই দুটি উত্তর মিলিয়ে (উত্তর 1 এবং উত্তর 2 ), আমি মনে করি যে ফাইলগুলি বাছাই ছাড়াই আপনার প্রয়োজনীয় ফলাফলটি পেতে পারেন:

#!/bin/bash
ans="matching_lines"

for file1 in *
do 
    for file2 in *
        do 
            if  [ "$file1" != "$ans" ] && [ "$file2" != "$ans" ] && [ "$file1" != "$file2" ] ; then
                echo "Comparing: $file1 $file2 ..." >> $ans
                perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' $file1 $file2 >> $ans
            fi
         done 
done

কেবল এটি সংরক্ষণ করুন, কার্যকর করার অধিকার দিন ( chmod +x compareFiles.sh) এবং এটি চালান। এটি বর্তমান কার্যনির্বাহী ডিরেক্টরিতে উপস্থিত সমস্ত ফাইল গ্রহণ করবে এবং ফলাফলটি "ম্যাচিংলাইনস" ফাইলের মধ্যে রেখে সমস্ত-তুলনা করে তুলবে।

জিনিসগুলি উন্নত করতে হবে:

  • ডিরেক্টরি ছেড়ে যান
  • সমস্ত ফাইল দুটিবার তুলনা করা থেকে বিরত থাকুন (ফাইল 1 বনাম ফাইল 2 এবং ফাইল 2 বনাম ফাইল 1)
  • মেলে স্ট্রিংয়ের পাশের লাইন নম্বরটি যুক্ত করুন

-2
rm file3.txt

cat file1.out | while read line1
do
        cat file2.out | while read line2
        do
                if [[ $line1 == $line2 ]]; then
                        echo $line1 >>file3.out
                fi
        done
done

এটি করা উচিত।


1
আপনি rm -f file3.txtযদি ফাইলটি মুছতে চলেছেন তবে আপনার সম্ভবত ব্যবহার করা উচিত ; ফাইল উপস্থিত না থাকলে কোনও ত্রুটির কথা জানায় না। ওহ, আপনার স্ক্রিপ্টটি যদি স্ট্যান্ডার্ড আউটপুটটিতে সহজে প্রতিধ্বনিত হয় তবে স্ক্রিপ্টের ব্যবহারকারীকে আউটপুট কোথায় যেতে হবে তা বেছে নিতে দেয় necessary শেষ পর্যন্ত, আপনি সম্ভবত ব্যবহার করতে চাইবেন$1$2 নির্দিষ্ট ফাইলের নাম ( file1.outএবং file2.out) এর পরিবর্তে এবং (কমান্ড লাইন আর্গুমেন্ট) । এটি অ্যালগরিদম ছেড়ে দেয়: এটি ধীর হতে চলেছে। এটি file2.outপ্রতিটি লাইনের জন্য একবার পড়তে চলেছে file1.out। ফাইলগুলি বড় হলে এটি ধীর হবে (একাধিক কিলোবাইট বলুন)।
জোনাথন লেফলার

যদিও এটি নামমাত্রভাবে কাজ করতে পারে যদি আপনার কাছে কোনও শেল মেটাচার্যাক্টর না থাকা ইনপুট থাকে (ইঙ্গিত: শেলচেক.net থেকে আপনি কী সতর্কতা পেয়েছেন তা দেখুন ), এই নিষ্পাপ পদ্ধতির মারাত্মকভাবে অক্ষম। একটি সরঞ্জাম grep -Fযা একটি ফাইলকে মেমোরিতে পড়ে এবং তারপরে অন্যটির একটি একক পাস উভয় ইনপুট ফাইলের উপর বারবার লুপিং এড়ায়।
ট্রিপল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.