টেক্সট ডিফ চেকার

আপনার মূল ও পরিবর্তিত টেক্সট পেস্ট করুন, তারপর কী পরিবর্তন হয়েছে তা দেখতে তুলনা করুন-এ ক্লিক করুন। যোগ হওয়া লাইন সবুজ রঙে, বাদ যাওয়া লাইন লাল রঙে, অপরিবর্তিত লাইন ধূসর রঙে হাইলাইট হয়। সম্পূর্ণ আপনার ব্রাউজারেই চলে — কিছুই আপলোড হয় না।

দুটি ফিল্ডেই টেক্সট দিন এবং তুলনা করুন-এ ক্লিক করুন।

টেক্সট ডিফ টুল কীভাবে ব্যবহার করবেন

  1. আপনার মূল টেক্সট বাম বক্সে এবং পরিবর্তিত টেক্সট ডান বক্সে পেস্ট করুন।
  2. যদি আপনি শুধু কনটেন্টের পরিবর্তনে আগ্রহী হন, ইনডেন্টেশনে নয়, তবে ঐচ্ছিকভাবে আগে/পরের খালি জায়গা উপেক্ষা করুন-এ টিক দিন।
  3. তুলনা করুন-এ ক্লিক করুন। ডিফ নিচে দেখা যায়: সবুজ লাইন যোগ হয়েছে, লাল লাইন বাদ গেছে, চিহ্নবিহীন লাইন অপরিবর্তিত।

টেক্সট ডিফ কী?

একটি "ডিফ" (difference এর সংক্ষিপ্ত রূপ) সেই ন্যূনতম পরিবর্তনগুলোর সেট দেখায় যা কোনো টেক্সটের একটি সংস্করণকে অন্যটিতে রূপান্তরিত করতে প্রয়োজন। ডিফ ভার্সন কন্ট্রোল (git, SVN), কোড রিভিউ, নথি তুলনা (কন্ট্রাক্ট সংস্করণ, প্রবন্ধ সংশোধন) এবং ডেটা যাচাইকরণে (রপ্তানি করা CSV ফাইল, কনফিগ ফাইলের তুলনা) ব্যবহৃত হয়।

এখানে ব্যবহৃত অ্যালগরিদম হলো LCS (দীর্ঘতম সাধারণ উপ-অনুক্রম — Longest Common Subsequence) — এটি লাইনের সেই দীর্ঘতম অনুক্রম খুঁজে বের করে যা দুটি টেক্সটেই সাধারণ, তারপর বাকি সবকিছু যোগ হওয়া বা বাদ যাওয়া হিসেবে চিহ্নিত করে। এটি সেই একই অ্যালগরিদম যা diff(1), git diff এবং বেশিরভাগ কোড-রিভিউ ডিফ ভিউকে শক্তি জোগায়।

Hunt ও McIlroy থেকে Myers পর্যন্ত: diff-এর একটি সংক্ষিপ্ত ইতিহাস

diff ইউটিলিটি Bell Labs-এ লেখা হয়েছিল এবং ১৯৭০-এর দশকের মাঝামাঝি Unix-এর সঙ্গে এসেছিল। এর অ্যালগরিদম ১৯৭৬ সালের জুনে James W. Hunt ও M. Douglas McIlroy Bell Labs Computing Science Technical Report "An Algorithm for Differential File Comparison." হিসেবে প্রকাশ করেন। Hunt প্রোটোটাইপ তৈরি করেন; McIlroy তা পরিমার্জন করেন। এটি প্রথম অ-হিউরিস্টিক (non-heuristic) ফাইল-তুলনা টুলগুলোর একটি ছিল, এবং এটি সমস্যাটিকে ঠিক সেভাবে সংজ্ঞায়িত করেছিল যেভাবে প্রতিটি ডিফ টুল আজও করে: দুটি ফাইলের দীর্ঘতম সাধারণ উপ-অনুক্রম (LCS) খুঁজুন, তারপর সেই সাধারণ মেরুদণ্ডের বাইরের সবকিছুকে যোগ হওয়া বা বাদ যাওয়া হিসেবে জানান।

এক দশক পরে, ১৯৮৬ সালে, Eugene W. Myers Algorithmica জার্নালে "An O(ND) Difference Algorithm and Its Variations" প্রকাশ করেন। Myers অ্যালগরিদম দ্রুত এবং বোঝা সহজ, এবং এটি Git ও অগণিত এডিটর ও রিভিউ টুলে ডিফল্ট হয়ে ওঠে। এই পৃষ্ঠায় আপনি যে ডিফ দেখছেন তা সেই একই LCS ভিত্তির উপর দাঁড়িয়ে আছে যা ওই দুটি গবেষণাপত্র প্রতিষ্ঠা করেছিল।

সংক্ষিপ্ততম এডিট স্ক্রিপ্ট হিসেবে ডিফ: Myers অ্যালগরিদম

Myers তুলনাকে একটি এডিট গ্রাফ (edit graph)-এ পথ-অনুসন্ধানের (path-finding) সমস্যা হিসেবে পুনর্গঠন করেন। কল্পনা করুন মূল ফাইলটি একটি গ্রিডের উপরে এবং পরিবর্তিত ফাইলটি পাশে নিচে রাখা। ডানদিকে যাওয়া একটি লাইন বাদ দেয়, নিচে যাওয়া একটি লাইন যোগ করে, এবং তির্যক (diagonal) যাওয়া এমন লাইন রাখে যা দুটিতেই মিলে যায়। সেরা ডিফ হলো উপরের-বাম কোণ থেকে নিচের-ডান কোণ পর্যন্ত সেই পথ যা সবচেয়ে বেশি তির্যক পদক্ষেপ নেয় — অর্থাৎ যেটিতে সবচেয়ে কম যোগ ও বাদ থাকে। যোগ ও বাদ অপারেশনের সেই ন্যূনতম সংখ্যা হলো সংক্ষিপ্ততম এডিট স্ক্রিপ্ট (shortest edit script)

এই অ্যালগরিদম O(ND) সময় ও স্থানে চলে, যেখানে N দুটি ইনপুটের সম্মিলিত দৈর্ঘ্য এবং D হলো এডিট দূরত্ব — সেই সংক্ষিপ্ততম এডিট স্ক্রিপ্টের আকার। গুরুত্বপূর্ণ ধর্ম হলো D, না N, প্রভাবশালী থাকে: যখন দুটি ফাইল প্রায় এক (ছোট D) তখন ডিফ প্রায় রৈখিক হয় এবং তাৎক্ষণিক অনুভূত হয়, যা ভার্সন কন্ট্রোলে ঠিক সাধারণ পরিস্থিতি। একই গবেষণাপত্রে বর্ণিত একটি পরিমার্জন একটি ভাগ-করে-জয়-করো (linear-space) কৌশল দিয়ে মেমরিকে O(N) পর্যন্ত কমিয়ে দেয়, যাতে বড় ফাইলও মেমরি নিঃশেষ না করে।

LCS দূরত্ব বনাম Levenshtein দূরত্ব

"এডিট দূরত্ব (edit distance)" পরিমাপের একটি পরিবার, এবং এদের মধ্যে দুটির পার্থক্য ব্যাখ্যা করে কেন ডিফ আউটপুট যেমন দেখায় তেমন দেখায়। Levenshtein দূরত্ব কোনো একটি স্ট্রিংকে অন্যটিতে রূপান্তর করতে প্রয়োজনীয় একক-অক্ষর যোগ, বাদ ও প্রতিস্থাপন (substitution)-এর ন্যূনতম সংখ্যা গণনা করে। LCS দূরত্ব — লাইন-ডিফের পেছনের মডেল — শুধু যোগ ও বাদ-এর অনুমতি দেয়; কোনো প্রতিস্থাপন অপারেশন থাকে না।

এই একটি সীমাবদ্ধতাই কারণ যে ডিফ কখনো কোনো লাইনকে "স্থানে পরিবর্তিত" হিসেবে দেখায় না। এটি পুরনো লাইনকে বাদ যাওয়া এবং নতুন লাইনকে যোগ হওয়া হিসেবে দেখায় — একটির বদলে দুটি অপারেশন। পাঠ্যপুস্তকের উদাহরণ kitten-কে sitting-এ রূপান্তরিত করে: Levenshtein দূরত্ব ৩ (k-কে s দিয়ে বদলান, e-কে i দিয়ে বদলান, g যোগ করুন), কিন্তু LCS দূরত্ব ৫, কারণ প্রতিটি প্রতিস্থাপনকে একটি বাদ ও একটি যোগ হিসেবে প্রকাশ করতে হয়। যেসব টুল লাইনের ভেতরের পরিবর্তন হাইলাইট করতে চায় তারা কোনো পরিবর্তিত লাইনের ভেতরে একটি দ্বিতীয়, সূক্ষ্মতর ডিফ চালায় — কিন্তু লাইন-স্তরের সিদ্ধান্ত বিশুদ্ধ LCS।

Git-এর চারটি ডিফ অ্যালগরিদম

Git আপনাকে --diff-algorithm দিয়ে অ্যালগরিদম বেছে নিতে দেয়। চারটিই একটি সঠিক ডিফ তৈরি করে; এরা এতে ভিন্ন হয় যে কোন সমানভাবে বৈধ সারিবিন্যাস (alignment) বেছে নেয়, যা ফলাফল কতটা পাঠযোগ্য তা বদলে দেয়।

অ্যালগরিদমএটি কীভাবে কাজ করেকীসের জন্য সেরা
Myers (ডিফল্ট)এডিট গ্রাফে লোভী (greedy) সংক্ষিপ্ততম-এডিট-স্ক্রিপ্ট অনুসন্ধান।সাধারণ ব্যবহার; দ্রুত এবং প্রায় সবসময় যথেষ্ট।
Minimalপ্রমাণিতভাবে সংক্ষিপ্ততম ডিফের নিশ্চয়তার জন্য Myers-এর লোভী হিউরিস্টিক ছেড়ে দেয়।ছোট ইনপুট যেখানে পরম ন্যূনতম গুরুত্বপূর্ণ; ধীর।
Patienceশুধু সেই লাইনগুলোর মিল করে যা দুটি ফাইলেই অনন্য, তাদের দীর্ঘতম বর্ধমান উপ-অনুক্রমে নোঙর করে, তারপর পুনরাবৃত্তি (recurse) করে।রিফ্যাক্টর ও পুনর্বিন্যাস, যেখানে Myers ভুল ব্রেস বা খালি লাইন সারিবদ্ধ করে দেয়।
Histogrampatience-এর একটি সম্প্রসারণ যা কম-ফ্রিকোয়েন্সির সাধারণ লাইনও সামলায়; তুলনীয়ভাবে দ্রুত।একটি পরিষ্কার ডিফল্ট বিকল্প; ফাংশন সরে গেলে পরিপাটি আউটপুট।

Patience ডিফ উদ্ভাবন করেন BitTorrent-এর নির্মাতা Bram Cohen। এর অন্তর্দৃষ্টি হলো অনন্য লাইনগুলো — কোনো বন্ধ ব্রেসের বদলে একটি স্বতন্ত্র ফাংশন সিগনেচার — সবচেয়ে অর্থপূর্ণ নোঙর হয়, তাই আগে সেগুলো সারিবদ্ধ করা এবং তাদের মাঝের ফাঁকগুলোতে পুনরাবৃত্তি করা এমন ডিফ তৈরি করে যা সেভাবে মেলে যেভাবে একজন মানুষ পরিবর্তন পড়ে। Histogram একই ধারণাকে পরিমার্জন করে এবং বড় রিফ্যাক্টরে প্রায়ই সবচেয়ে শান্ত থাকে।

লাইন, শব্দ ও অক্ষর স্তরের সূক্ষ্মতা

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

শব্দ-স্তরের ডিফ খালি জায়গায় টোকেনাইজ করে এবং গদ্যের জন্য উপযুক্ত, যেখানে কোনো দীর্ঘ অনুচ্ছেদে এক-শব্দের পরিবর্তন পুরো লাইনকে চিহ্নিত করা উচিত নয়। অক্ষর-স্তরের ডিফ সবচেয়ে সূক্ষ্ম স্তর, কোনো শব্দের ভেতরে পরিবর্তিত ঠিক অক্ষরগুলো হাইলাইট করার জন্য উপযোগী, কিন্তু যেকোনো বড় কিছুতে এটি অগোছালো লাগে। অনেক এডিটর দুটিকে মিলিয়ে দেয়: পরিবর্তিত অঞ্চল খুঁজতে একটি লাইন-ডিফ, তারপর সঠিক পরিবর্তন হাইলাইট করতে প্রতিটি অঞ্চলের ভেতরে একটি শব্দ- বা অক্ষর-ডিফ।

ইউনিফায়েড ডিফ ফরম্যাট পড়া

ইউনিফায়েড ডিফ (unified diff) হলো সেই ফরম্যাট যা আপনি git diff, প্যাচ ও পুল রিকোয়েস্টে দেখেন। এটি দুটি ফাইল হেডার দিয়ে শুরু হয় — মূলে --- এবং নতুনে +++ চিহ্ন — এবং তারপর পরিবর্তনগুলোকে হাঙ্ক (hunks)-এ দলবদ্ধ করে। প্রতিটি হাঙ্ক @@ -l,s +l,s @@ রূপের হেডার দিয়ে শুরু হয়, যেখানে প্রথম জোড়া মূল ফাইলে শুরুর লাইন ও লাইন-সংখ্যা এবং দ্বিতীয় জোড়া নতুন ফাইলের জন্য একই।

কোনো হাঙ্কের ভেতরে, প্রতিটি লাইন একটি একক-অক্ষর উপসর্গ বহন করে: অপরিবর্তিত প্রসঙ্গ (context) লাইনের জন্য একটি স্পেস, মূল থেকে বাদ যাওয়া লাইনের জন্য একটি মাইনাস, এবং নতুন সংস্করণে যোগ হওয়া লাইনের জন্য একটি প্লাস। ডিফল্টভাবে কিছু অপরিবর্তিত প্রসঙ্গ লাইন (সাধারণত তিনটি) প্রতিটি পরিবর্তনকে ঘিরে থাকে যাতে ফাইল সামান্য সরে যাওয়ার পরও প্যাচ প্রয়োগ করা যায়। পুরনো কনটেক্সট ডিফ (context diff) ফরম্যাট একই তথ্য দিত কিন্তু আগে ও পরের ব্লক আলাদাভাবে ছাপত এবং পরিবর্তিত লাইনগুলোকে ! দিয়ে চিহ্নিত করত; ইউনিফায়েড ফরম্যাট বেশি সংক্ষিপ্ত কারণ এটি দুই পক্ষকে পরস্পর গেঁথে দেয়, এবং এটিই ডিফল্ট হয়ে উঠেছে।

তিন-দিকের মার্জ ও কনফ্লিক্ট

একটি সাধারণ দুই-দিকের ডিফ বলতে পারে না দুটি ভিন্ন ফাইলের কোনটি "সঠিক"। একটি তিন-দিকের মার্জ (three-way merge) সাধারণ পূর্বপুরুষ (common ancestor)-কে একটি রেফারেন্স হিসেবে যোগ করে। diff3-এর মতো টুল দুটি সংস্করণকে সেই ভিত্তির সঙ্গে তুলনা করে: শুধু এক পক্ষে করা পরিবর্তন স্বয়ংক্রিয়ভাবে প্রয়োগ হয়, আর যে অঞ্চল দুই পক্ষ ভিন্নভাবে বদলেছে, তা একটি মার্জ কনফ্লিক্ট (merge conflict) হিসেবে জানানো হয় — Git-এ পরিচিত <<<<<<< / ======= / >>>>>>> চিহ্ন। এটি চেনা যে কনফ্লিক্ট কেবল "দুই পক্ষ পূর্বপুরুষের সাপেক্ষে একই লাইন সম্পাদনা করেছে", এদের সমাধান অনেক কম রহস্যময় করে তোলে।

বাস্তবে ডিফিং কোথায় ব্যবহৃত হয়

  • কোড রিভিউ। প্রতিটি পুল রিকোয়েস্ট একটি ডিফ; রিভিউয়াররা পুরো ফাইল আবার পড়ার বদলে যোগ ও বাদ যাওয়া লাইন পড়েন।
  • নথি ও কন্ট্রাক্ট তুলনা। কোনো চুক্তি, নীতি বা প্রবন্ধের দুটি সংশোধনের তুলনা করে ঠিক দেখা কোন শব্দগুলো বদলেছে।
  • কনফিগারেশন ড্রিফট। কোনো সার্ভারের লাইভ কনফিগারেশনকে পরিচিত-সঠিক সংস্করণের সঙ্গে ডিফ করে অনিচ্ছাকৃত পরিবর্তন খুঁজে বের করা।
  • লগ ও ডেটা বিশ্লেষণ। দুটি রপ্তানি, দুটি CSV স্ন্যাপশট বা দুটি লগ ফাইলের তুলনা করে ঠিক আলাদা করা রান-এর মধ্যে কী সরেছে।
  • চৌর্যবৃত্তি ও সাদৃশ্য শনাক্তকরণ। সাধারণ উপ-অনুক্রমের আকার এই বিষয়ের একটি সরাসরি পরিমাপ যে দুটি নথি কতটা এক।

প্রতিটি ক্ষেত্রে প্রশ্নটি সেই একই যার উত্তর Hunt, McIlroy ও Myers দিয়েছিলেন: সেই সংক্ষিপ্ততম, সবচেয়ে স্পষ্ট পরিবর্তনগুলোর সেট কী যা প্রথম টেক্সটকে দ্বিতীয়টিতে রূপান্তরিত করে?

লাইন-ডিফের সীমাবদ্ধতা: সরে যাওয়া ব্লক ও অগোছালো আউটপুট

একটি লাইন-ডিফ একটি ঠিক প্রশ্নের উত্তর দেয় — দুটি ফাইলের মধ্যে লাইন যোগ ও বাদের সংক্ষিপ্ততম অনুক্রম — এবং সেই দৃষ্টিভঙ্গির কিছু বাস্তব অন্ধ বিন্দু আছে যা বোঝা উপযোগী। সবচেয়ে সাধারণ হলো সরে যাওয়া কোড (moved code): আপনি যদি কোনো ফাইলের উপর থেকে একটি ফাংশন কেটে তা নিচে সেঁটে দেন, তবে একটি সাধারণ ডিফের কাছে "সরে যাওয়া" বলে কোনো ধারণা নেই। এটি ব্লকটিকে এক জায়গায় বাদ যাওয়া এবং অন্য জায়গায় যোগ হওয়া হিসেবে জানায়, যাতে পরিবর্তনের আপাত আকার দ্বিগুণ দেখায়। কিছু টুল ডিফের উপরে একটি আলাদা পাস হিসেবে সরে-যাওয়া শনাক্তকরণ যোগ করে; অন্তর্নিহিত LCS ফলাফল তবুও দুটি কপিকে স্বাধীনভাবে গণ্য করে।

দ্বিতীয় সীমাবদ্ধতা হলো সারিবিন্যাস অস্পষ্টতা (alignment ambiguity)। যখন কোনো ফাইলে অনেকগুলো এক-রকম লাইন থাকে — খালি লাইন, বন্ধ ব্রেস, পুনরাবৃত্ত বয়লারপ্লেট — তখন কয়েকটি ভিন্ন ডিফ সমানভাবে ন্যূনতম হতে পারে, এবং একটি লোভী Myers অনুসন্ধান এমন একটি বেছে নিতে পারে যা ভুল ব্রেসকে ভুল ব্রেসের সঙ্গে জোড়ে, যাতে একটি পরিপাটি সম্পাদনা ছড়ানো দেখায়। এটি ঠিক সেই সমস্যা যা patience ও histogram অ্যালগরিদম আগে অনন্য লাইনে নোঙর করে লক্ষ্য করে। তৃতীয়টি হলো লাইন-ডিফ লাইনের ভেতরের পরিবর্তনের প্রতি অন্ধ: কোনো দীর্ঘ লাইনে একটি অক্ষর সম্পাদনা করুন এবং পুরো লাইন চিহ্নিত হয়ে যায়, এই কারণেই গদ্যের তুলনা প্রায়ই একটি শব্দ-স্তরের পাস থেকে উপকৃত হয়।

এর কোনোটিই লাইন-ডিফকে ভুল বানায় না — এটি কোড ও কনফিগারেশনের জন্য সঠিক ডিফল্ট — কিন্তু এর অনুমানগুলো জানা ব্যাখ্যা করে কেন দুটি টুল একই "পরিবর্তন" ভিন্নভাবে দেখাতে পারে, এবং অ্যালগরিদম বা সূক্ষ্মতা বদলানো কখনো কখনো কেন একটি বিভ্রান্তিকর ডিফকে স্পষ্ট করে তোলে।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

এটি কোন অ্যালগরিদম ব্যবহার করে?
LCS (দীর্ঘতম সাধারণ উপ-অনুক্রম — Longest Common Subsequence) অ্যালগরিদম ব্যবহার করে লাইন-বাই-লাইন ডিফ — একই পদ্ধতি যা Unix-এ diff(1), git diff এবং বেশিরভাগ কোড-রিভিউ টুল ব্যবহার করে। দুটি টেক্সটেই থাকা লাইনগুলো অপরিবর্তিত দেখানো হয়; শুধু মূল টেক্সটে থাকা লাইন বাদ যাওয়া (লাল) হিসেবে চিহ্নিত হয়; শুধু পরিবর্তিত টেক্সটে থাকা লাইন যোগ হওয়া (সবুজ) হিসেবে চিহ্নিত হয়।
আমার টেক্সট কি কোনো সার্ভারে আপলোড হয়?
না। ডিফ সম্পূর্ণ আপনার ব্রাউজারেই JavaScript দিয়ে চলে। আপনার টেক্সট কখনো আপনার ডিভাইস থেকে বাইরে যায় না এবং পৃষ্ঠা লোড হওয়ার পর অফলাইনেও কাজ করে।
আমি কি কোড ডিফ করতে পারি?
হ্যাঁ। এই টুল যেকোনো প্লেইন টেক্সট ডিফ করে, যার মধ্যে সোর্স কোড, কনফিগারেশন ফাইল, JSON, CSV, গদ্য ও মার্কডাউন অন্তর্ভুক্ত। এটি সিনট্যাক্স হাইলাইটিং প্রয়োগ করে না, তবে লাইন-স্তরের ডিফ ইনডেন্টেশন ও বিরামচিহ্ন সঠিকভাবে সামলায়।
আমি কত বড় টেক্সট তুলনা করতে পারি?
LCS অ্যালগরিদমের সময়-জটিলতা O(n×m), তাই খুব বড় ফাইল (হাজার হাজার লাইন) ধীর হতে পারে। কয়েকশো লাইন পর্যন্ত নথির জন্য ডিফ তাৎক্ষণিক হয়। বড় ফাইলের জন্য কোনো ডেস্কটপ ডিফ টুল (diff, vimdiff, VS Code compare) ব্যবহারের কথা বিবেচনা করুন।
"খালি জায়গা উপেক্ষা করুন" কী করে?
টিক দিলে, তুলনার আগে প্রতিটি লাইন ট্রিম করা হয়, তাই শুধু আগে/পরের খালি জায়গার পরিবর্তনযুক্ত লাইন অপরিবর্তিত হিসেবে ধরা হয়। এটি Unix-এ diff -b এর সমতুল্য — যে কোড পুনরায় ফরম্যাট বা পুনরায় ইনডেন্ট করা হয়েছে তার তুলনার জন্য উপযোগী।

সম্পর্কিত টুল

আরও টুল দেখুন

সব 69টি টুল দেখুন →

আপনার সাইটে এই টুলটি এমবেড করুন — বিনামূল্যে

সব এমবেডযোগ্য টুল →

যেকোনো পৃষ্ঠা, পোস্ট বা টেমপ্লেটে Text Diff Checker যোগ করুন। এটি চিরকাল বিনামূল্যে — কোনো সাইন-আপ নেই, উইজেটের ভিতরে কোনো বিজ্ঞাপন নেই। একমাত্র শর্ত: ছোট দৃশ্যমান কৃতিত্ব লিঙ্কটি রেখে দিন।

উইজেটটি প্রিভিউ করুন