লাইন দ্বারা দুটি ফাইল লাইন তুলনা করুন এবং অন্য ফাইলের মধ্যে পার্থক্য তৈরি করুন


120

আমি ফাইল 2 এর সাথে ফাইল 2 এর সাথে তুলনা করতে এবং এমন ফাইল 3 উত্পন্ন করতে চাই যাতে ফাইল 1-এ লাইন রয়েছে যা ফাইল 2 তে উপস্থিত নেই।


আমি ভিন্ন ভিন্ন চেষ্টা করেছিলাম কিন্তু এটি বিভিন্ন লাইনের সামনে কিছু নম্বর এবং অন্যান্য চিহ্ন তৈরি করে যা ফাইলগুলির তুলনা করা আমার পক্ষে কঠিন করে তোলে।
সূর্য

উত্তর:


215

ডিফ (1) উত্তরটি নয়, তবে কম (1)।

NAME
       comm - compare two sorted files line by line

SYNOPSIS
       comm [OPTION]... FILE1 FILE2

...

       -1     suppress lines unique to FILE1

       -2     suppress lines unique to FILE2

       -3     suppress lines that appear in both files

সুতরাং

comm -2 -3 file1 file2 > file3

ইনপুট ফাইলগুলি বাছাই করতে হবে। যদি তা না হয় তবে প্রথমে তাদের বাছাই করুন। এটি একটি অস্থায়ী ফাইল, বা ...

comm -2 -3 <(sort file1) <(sort file2) > file3

আপনার শেল প্রক্রিয়া প্রতিস্থাপন সমর্থন করে (প্রদত্ত)


1
মনে রাখবেন যে দুটি ফাইলের সাজানো হতে হবে এবং অদ্বিতীয়
অ্যান্ডি

6
আপনি বিকল্পগুলি একসাথে গ্রুপ করতে পারেন:comm -23
পাওলো এম

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

@ ইগরহানস: যদি ফাইলটিতে উদাহরণস্বরূপ "3 \ n1 \ n3 \ n2 \ n" রেখাগুলি থাকে তবে প্রথমে আরোহণ বা উতরাইয়ের ক্রমটি পুনরায় সাজানো আবশ্যক যেমন "\ 1 \ n2 \ n3 \ n3 \ n" সদৃশ সহ সংলগ্ন। এটি "বাছাই করা" এবং উভয় ফাইলই একই ধরণের বাছাই করতে হবে। যখন নতুন ফাইলে নতুন লাইন থাকে তখন সেগুলি "বিদ্যমান লাইনের মধ্যে" থাকলে কিছু যায় আসে না কারণ তারা সাজানোর পরেও তারা সাজানো ক্রমে থাকে।
sorpigal

47

ইউনিক্স ইউটিলিটি diffহ'ল এই উদ্দেশ্যে।

$ diff -u file1 file2 > file3

বিকল্পগুলি, বিভিন্ন আউটপুট ফর্ম্যাট ইত্যাদির জন্য ম্যানুয়াল এবং ইন্টারনেট দেখুন etc.


7
যে অনুরোধ কাজ করে না; এটি অন্যান্য উত্তরে প্রস্তাবিত কমান্ডলাইন সুইচ ব্যবহার করেও অতিরিক্ত অক্ষরের একটি গুচ্ছ সন্নিবেশ করায়।
xenocyon

20

এটি বিবেচনা করুন:
ফাইল a.txt:

abcd
efgh

ফাইল b.txt:

abcd

আপনি এর সাথে পার্থক্যটি খুঁজে পেতে পারেন:

diff -a --suppress-common-lines -y a.txt b.txt

আউটপুটটি হবে:

efgh 

আপনি আউটপুট ফাইলে (c.txt) ব্যবহার করে আউটপুটটিকে পুনঃনির্দেশ করতে পারেন:

diff -a --suppress-common-lines -y a.txt b.txt > c.txt

এটি আপনার প্রশ্নের উত্তর দেবে:

"... এতে ফাইল 1 এ রেখা রয়েছে যা ফাইল 2 তে উপস্থিত নেই"


2
এই উত্তরের দুটি সীমাবদ্ধতা রয়েছে: (1) এটি কেবল সংক্ষিপ্ত রেখাগুলির জন্য কাজ করে (ডিফল্টরূপে 80 টিরও কম অক্ষর, যদিও এটি সংশোধন করা যায়) এবং আরও গুরুত্বপূর্ণ, (2) এটি প্রতিটিটির শেষে একটি "<" যুক্ত করে লাইন যা অবশ্যই অন্য প্রোগ্রামের সাথে সরিয়ে নিতে হবে (যেমন, awk, সেড)।
সার্জুট

অনেক ক্ষেত্রে, আপনি এটিও ব্যবহার করতে চাইবেন -d, যা diffসবচেয়ে ছোট সম্ভাব্যতম পার্থক্যটি সন্ধানের জন্য যথাসাধ্য চেষ্টা করবে । -i, -E, -w, -Bএবং --suppress-blank-emptyএছাড়াও দরকারী মাঝেমধ্যে হতে পারে, যদিও সব সময় নয়। আপনার ব্যবহারের ক্ষেত্রে কী মানায় তা যদি আপনি না জানেন তবে diff --helpপ্রথমে চেষ্টা করুন (যখন আপনি কোনও কমান্ড কী করতে পারেন তা জানেন না তবে এটি সাধারণত একটি ভাল ধারণা)।
ডিম হ্যান্স

এছাড়াও, --line-format =% L ব্যবহার করে, আপনি কোনও অতিরিক্ত অক্ষর তৈরি করা থেকে আলাদা থাকবেন (কমপক্ষে, সহায়তা বলছে এটি এ জাতীয় কাজ করে, তবে এটি চেষ্টা করে দেখতে)।
ডিম হ্যান্স

এছাড়াও এই খাটো এবং একই কাজ করে বলে মনে হয় stackoverflow.com/a/27667185/1179925
mrgloom

8

কখনও কখনও diffআপনার প্রয়োজনীয় ইউটিলিটিটি হয় তবে কখনও কখনও joinএটি আরও উপযুক্ত। ফাইলগুলি প্রাক-বাছাই করা দরকার বা আপনি যদি এমন শেল ব্যবহার করছেন যা প্রক্রিয়া প্রতিস্থাপন যেমন বাশ, কেএসএস বা জেডএস সমর্থন করে তবে আপনি ফ্লাইতে বাছাই করতে পারেন।

join -v 1 <(sort file1) <(sort file2)

আপনার এই জন্য একটি পদক পাওয়া উচিত! আমি ঠিক 2 ঘন্টার জন্য যা খুঁজছিলাম ঠিক
সেটাই ছিল

7

চেষ্টা

sdiff file1 file2

এটি আমার জন্য বেশিরভাগ ক্ষেত্রে ব্যবহারযোগ্যভাবে আরও ভাল কাজ করে। লাইনের ক্রমটি গুরুত্বপূর্ণ না হলে আপনি আগে ফাইলগুলি বাছাই করতে চাইতে পারেন (উদাহরণস্বরূপ কিছু পাঠ্য কনফিগারেশন ফাইল)।

উদাহরণ স্বরূপ,

sdiff -w 185 file1.cfg file2.cfg

1
ভাল ইউটিলিটি! আমি কীভাবে এটি পৃথকীকরণের রেখা চিহ্নিত করে তা পছন্দ করি। কনফিগারদের তুলনা করা এটি আরও সহজ করে তোলে। এই একসাথে সাজানোর জন্য একটি মারাত্মক কম্বো (যেমন sdiff <(sort file1) <(sort file2))
jmagnusson

3

আপনার যদি কোরিউটিলেস দিয়ে এটি সমাধান করার দরকার হয় তবে গ্রহণযোগ্য উত্তরটি ভাল:

comm -23 <(sort file1) <(sort file2) > file3

আপনি এসডি (স্ট্রিম ডিফ) ব্যবহার করতে পারেন , যার জন্য বাছাই বা বিকল্প প্রয়োগ প্রক্রিয়া প্রয়োজন হয় না এবং অসীম স্ট্রিমগুলি সমর্থন করে যেমন:

cat file1 | sd 'cat file2' > file3

সম্ভবত এই উদাহরণে এতটা উপকারের পরিমাণ না, তবে এখনও এটি বিবেচনা করুন; কিছু কিছু ক্ষেত্রে আপনি ব্যবহার করতে সক্ষম হবেন না commকিংবা grep -Fকিংবা diff

এখানে একটি ব্লগপোস্ট আমি টার্মিনালে বিভিন্ন স্ট্রিমগুলি সম্পর্কে লিখেছিলাম, যা এসডি প্রবর্তন করে।


3

তবুও, কোন grepসমাধান নেই?

  • কেবল ফাইল 2 এ বিদ্যমান লাইনগুলি:

    grep -Fxvf file1 file2 > file3
  • লাইনগুলি যা কেবল ফাইল 1 এ বিদ্যমান:

    grep -Fxvf file2 file1 > file3
  • উভয় ফাইলে বিদ্যমান লাইনগুলি:

    grep -Fxf file1 file2 > file3

2

ইতিমধ্যে অনেক উত্তর, কিন্তু তাদের কোনওই IMHO নিখুঁত নয়। থানাটোসের জবাব প্রতি লাইনে কিছু অতিরিক্ত অক্ষর রেখে দেয় এবং সর্পিগালের উত্তরের জন্য ফাইলগুলি বাছাই বা প্রাক-বাছাই করা দরকার, যা সমস্ত পরিস্থিতিতে পর্যাপ্ত নাও হতে পারে।

আমি মনে করি লাইন ভিন্ন ভিন্ন অন্য কিছুই হয় পাবার সবচেয়ে ভালো উপায় (কোন অতিরিক্ত অক্ষর, কোন পুনরায় ক্রম) তার সংমিশ্রণ diff, grepএবংawk (বা অনুরূপ)।

যদি লাইনগুলিতে কোনও "<" না থাকে, একটি সংক্ষিপ্ত ওয়ান-লাইনার হতে পারে:

diff urls.txt* | grep "<" | sed 's/< //g'

তবে এটি লাইনগুলি থেকে "<" (স্থানের চেয়ে কম) এর প্রতিটি উদাহরণ সরিয়ে ফেলবে, যা সর্বদা ঠিক থাকে না (যেমন উত্স কোড)। সবচেয়ে নিরাপদ বিকল্পটি হ'ল অ্যাডক ব্যবহার করা:

diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'

এই ওয়ান-লাইনার উভয় ফাইলকে পৃথক করে, তারপরে ভিন্নতার এড-স্টাইল আউটপুট ফিল্টার করে, তারপরে পার্থক্য যুক্ত করা << "অপসারণ করে। লাইনগুলিতে কিছু "<" থাকলেও এটি কাজ করে।


1
কমকে বাছাই করার প্রয়োজন নেই (আরও নতুন সংস্করণে?) - কেবল - ননচেক-ক্রম ব্যবহার করুন। আমি এগুলি অনেক ব্যবহার করি যখন সি এল আই থেকে সিএসভিগুলিতে
হেরফের করি

2

আমি আশ্চর্য হয়েছি কেউ পাশের পাশাপাশি আউটপুট উত্পাদনdiff -y করার জন্য উল্লেখ করেনি , উদাহরণস্বরূপ:

diff -y file1 file2 > file3

এবং এর মধ্যে file3(বিভিন্ন রেখার |মাঝখানে একটি চিহ্ন রয়েছে):

same     same
diff_1 | diff_2

1

ডিফ ইউটিলিটিটি ব্যবহার করুন এবং আউটপুটে <টি দিয়ে শুরু হওয়া লাইনগুলি বের করুন


0
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt

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


1
এটি একটি খারাপ ধারণা। আপনাকে শুরু করে লাইনগুলি সংশোধন করতে হবে <। আপনি যদি ইনপুট ফাইলগুলির ক্রমটি অদলবদল করেন তবে এটি দেখতে পাবেন। এমনকি যদি আপনি এটি করেন তবে আপনি grepআরও সেড ব্যবহার করে বাদ দিতে চাইবেন : `ডিফ একটি এ 1 এ 2 | কিন্তু '/> / গুলি ///' `এখনও ধারণকারী লাইন ভাঙ্গতে পারে >বা <অধিকার পরিস্থিতি এবং এখনও লাইন সংখ্যা বর্ণনা অতিরিক্ত লাইন ছেড়ে। আপনি এই পদ্ধতির চেষ্টা চেয়েছিলেন একটি ভাল উপায় হতে পারে: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
sorpigal

0

আপনি diffনিম্নলিখিত আউটপুট বিন্যাস সঙ্গে ব্যবহার করতে পারেন :

diff --old-line-format='' --unchanged-line-format='' file1 file2

--old-line-format=''ফাইললাইনের তুলনায় লাইনটি আলাদা থাকলে ফাইল 1 এর জন্য আউটপুট অক্ষম করুন।
--unchanged-line-format='', লাইনগুলি একই থাকলে আউটপুট অক্ষম করুন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.