কীভাবে প্যাচ এবং ডিফ ব্যবহার করতে হবে দুটি ফাইল একত্রীকরণ করতে এবং স্বয়ংক্রিয়ভাবে বিবাদগুলি সমাধান করতে


19

আমি ডিফ এবং প্যাচ সম্পর্কে পড়েছি তবে আমার কী প্রয়োজন তা কীভাবে প্রয়োগ করব তা আমি বুঝতে পারি না। আমার ধারণা এটি খুব সহজ, তাই আমার সমস্যাটি দেখানোর জন্য এই দুটি ফাইল নিন:

a.xml

<resources>
   <color name="same_in_b">#AAABBB</color>
   <color name="not_in_b">#AAAAAA</color>
   <color name="in_b_but_different_val">#AAAAAA</color>
   <color name="not_in_b_too">#AAAAAA</color>
</resources>

b.xml

<resources>
   <color name="same_in_b">#AAABBB</color>
   <color name="in_b_but_different_val">#BBBBBB</color>
   <color name="not_in_a">#AAAAAA</color>
</resources>

আমি একটি আউটপুট রাখতে চাই, যা দেখতে এটির (অর্ডার কোনও ব্যাপার নয়):

<resources>
   <color name="same_in_b">#AAABBB</color>
   <color name="not_in_b">#AAAAAA</color>
   <color name="in_b_but_different_val">#BBBBBB</color>
   <color name="not_in_b_too">#AAAAAA</color>
   <color name="not_in_a">#AAAAAA</color>
</resources>

মার্জটিতে এই সাধারণ নিয়মগুলির সাথে সমস্ত লাইন থাকা উচিত:

  1. যে কোনও লাইন কেবলমাত্র ফাইলগুলির মধ্যে একটি
  2. যদি কোনও লাইনের একই নামের ট্যাগটি থাকে তবে ভিন্ন মান থাকে তবে দ্বিতীয়টি থেকে মানটি নিয়ে যান

আমি এই টাস্কটি ব্যাশ স্ক্রিপ্টের মধ্যে প্রয়োগ করতে চাই, সুতরাং অন্য প্রোগ্রামামের চেয়ে আরও ভালভাবে ফিট করা থাকলে এটি অবশ্যই আলাদা এবং প্যাচ দিয়ে করা দরকার হবে না


diffকোন ফাইলগুলিতে কোন ফাইলগুলি আপনাকে অন্য ফাইল নয় তা বলতে পারে তবে কেবল সম্পূর্ণ রেখার গ্রানুলারিটিতে। patchএকই জাতীয় ফাইলটিতে একই পরিবর্তনগুলি করার জন্য কেবল উপযুক্ত (সম্ভবত একই ফাইলের একটি ভিন্ন সংস্করণ, বা সম্পূর্ণ আলাদা ফাইল যেখানে তবে প্রতিটি পরিবর্তনের জন্য লাইন সংখ্যা এবং আশেপাশের লাইনগুলি আপনার মূল ফাইলের অনুরূপ)। সুতরাং না, তারা এই কাজের জন্য বিশেষভাবে উপযুক্ত নয়। আপনি হয়ত দেখতে চান wdiffতবে সমাধানটির জন্য সম্ভবত একটি কাস্টম স্ক্রিপ্ট প্রয়োজন। যেহেতু আপনার ডেটা এক্সএমএলের মতো দেখাচ্ছে তাই আপনি কিছু এক্সএসএল সরঞ্জামের সন্ধান করতে পারেন।
ট্রিপলি

1
কাস্টম স্ক্রিপ্ট সহ সমস্ত উত্তর? মার্জ করা একটি স্ট্যান্ডার্ড এবং জটিল সমস্যা এবং এর জন্য ভাল সরঞ্জাম রয়েছে। চাকা পুনরুদ্ধার করবেন না।
অ্যালেক্সিস

উত্তর:


23

আপনার এটার দরকার নেই patch; এটি ফাইলগুলি অপরিবর্তিত অংশ ব্যতীত পরিবর্তনগুলি আহরণ এবং এগুলি প্রেরণের জন্য।

কোনও ফাইলের দুটি সংস্করণ মার্জ করার জন্য সরঞ্জামটি রয়েছে mergeতবে যেমনটি @vonbrandলিখেছেন, আপনার "বেস" ফাইলটি দরকার যা থেকে আপনার দুটি সংস্করণ ডাইভার্ট করা হয়েছে। এটি ছাড়া মার্জ করতে, এটি ব্যবহার করুন diff:

diff -DVERSION1 file1.xml file2.xml > merged.xml

এটি সি-স্টাইল #ifdef/ #ifndef"প্রিপ্রসেসর" কমান্ডের প্রতিটি সেট পরিবর্তনের সাথে যুক্ত করে রাখবে :

#ifdef VERSION1
<stuff added to file1.xml>
#endif
...
#ifndef VERSION1
<stuff added to file2.xml>
#endif

যদি কোনও লাইন বা অঞ্চল দুটি ফাইলের মধ্যে পৃথক হয়, আপনি একটি "দ্বন্দ্ব" পাবেন যা দেখতে এরকম দেখাচ্ছে:

#ifndef VERSION1
<version 1>
#else /* VERSION1 */
<version 2>
#endif /* VERSION1 */

সুতরাং একটি ফাইলের মধ্যে আউটপুট সংরক্ষণ করুন, এবং একটি সম্পাদক এ এটি খুলুন। যে জায়গাগুলি #elseআসে সেগুলি অনুসন্ধান করুন এবং ম্যানুয়ালি সমাধান করুন। তারপরে ফাইলটি সংরক্ষণ করুন এবং grep -vবাকি #if(n)defএবং #endifলাইনগুলি থেকে মুক্তি পেতে এটিকে চালনা করুন :

grep -v '^#if' merged.xml | grep -v '^#endif' > clean.xml

ভবিষ্যতে, ফাইলটির মূল সংস্করণটি সংরক্ষণ করুন। mergeঅতিরিক্ত তথ্যের সাহায্যে আপনাকে আরও ভাল ফলাফল দিতে পারে। (তবে সাবধানতা অবলম্বন করুন: mergeস্থানে থাকা ফাইলগুলির মধ্যে একটির সম্পাদনা করুন, আপনি যদি না ব্যবহার করেন তবে -pম্যানুয়ালটি পড়ুন)।


আমার যদি কোনও বিরোধ হয় তবে এর জন্য আমি কিছু যুক্ত করেছিsed -e "s/^#else.*$/\/\/ conflict/g"
লকউব্রব

1
আমি মনে করি না এটি একটি ভাল ধারণা। আমি আমার উত্তরে যেমন লিখেছি #else, সংঘাতের সমাধানের সময় আপনার সম্পাদকীয়তে ম্যানুয়ালি লাইনগুলি সরিয়ে ফেলা উচিত ।
Alexis

6

merge(1) আপনি যা চান তা সম্ভবত নিকটতম তবে এটির জন্য আপনার দুটি ফাইলের একটি সাধারণ পূর্বপুরুষের প্রয়োজন।

এটি করার একটি (নোংরা!) উপায়:

  1. প্রথম এবং শেষ লাইনগুলি পরিত্রাণ পান, grep(1)এগুলি বাদ দিতে ব্যবহার করুন
  2. একসাথে ফলাফলগুলি ধ্বংস
  3. sort -u বাছাই করা তালিকা ছেড়ে দেয়, সদৃশগুলি সরিয়ে দেয়
  4. প্রথম / শেষ লাইনটি প্রতিস্থাপন করুন

হাম ... লাইন ধরে কিছু:

echo '<resources>'; grep -v resources file1 file2 | sort -u; echo '</resources>'

কি হতে পারে.


এই বিশেষ উদাহরণে কাজ করে, তবে সাধারণভাবে নয়: সাধারণ name in_b_but_different_valমানটির যদি মানটির #00AABBমান থাকে তবে এটি প্রথমটির পরিবর্তে দ্বিতীয় মানটি মুছে ফেলবে
রাফায়েল টি

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

@ আলঝাইমার, আমাদের দেখানোর জন্য কিছু সহজ চাবুক ...
ভোনব্র্যান্ড

দৃশ্যত diff3একইভাবে কাজ করে। একটি সাধারণ পূর্বপুরুষের ফাইলের প্রয়োজন। কেন এমন কোনও সাধারণ সিএলআই সরঞ্জাম নেই যা কেবল 2 টি ফাইল একসাথে যা diffদেখায় তার ভিত্তিতে 2 টি ফাইল একত্রিত করে ।
CMCDragonkai

5

sdiff (1) - পাশাপাশি ফাইলের পার্থক্য একত্রিত করা

--outputবিকল্পটি ব্যবহার করুন , এটি ইন্টারেক্টিভভাবে যে কোনও দুটি ফাইল একীভূত করবে। আপনি পরিবর্তন নির্বাচন করতে বা পরিবর্তন সম্পাদনা করতে সাধারণ কমান্ড ব্যবহার করেন ।

আপনার EDITORপরিবেশের পরিবর্তনশীল সেট করা আছে তা নিশ্চিত করা উচিত । "Eb" এর মতো কমান্ডের জন্য ডিফল্ট সম্পাদক সাধারণত edএকটি লাইন সম্পাদক

EDITOR=nano sdiff -o merged.txt file1.txt file2.txt

1
আমি vimআরও ভাল হিসাবে এডিটর হিসাবে ব্যবহার দেখতে। তবে এটিই সেরা সমাধান, এটি diffকমান্ডের সাথেও আসে !
সিএমসিডিগ্রাগনকাই

1

এখানে একটি সাধারণ সমাধান যা 10 টি ফাইল পর্যন্ত মার্জ করে কাজ করে :

#!/bin/bash

strip(){
    i=0
    for f; do
        sed -r '
            /<\/?resources>/ d
            s/>/>'$((i++))'/
        ' "$f"
    done
}

strip "$@" | sort -u -k1,1 -t'>' | sed '
    1 s|^|<resources>\n|
    s/>[0-9]/>/
    $ a </resources>
'

দয়া করে নোট করুন যেটি প্রথমে আসে সেই যুক্তিটির প্রাধান্য রয়েছে যাতে আপনাকে কল করতে হবে:

script b.xml a.xml

সাধারণ মান b.xmlপরিবর্তে রাখা থেকে পেতে a.xml

script b.xml a.xml আউট:

<resources>
   <color name="in_b_but_different_val">#BBBBBB</color>
   <color name="not_in_a">#AAAAAA</color>
   <color name="not_in_b">#AAAAAA</color>
   <color name="not_in_b_too">#AAAAAA</color>
   <color name="same_in_b">#AAABBB</color>
</resources>

1

আরেকটি ভয়ঙ্কর হ্যাক - সরল করা যেতে পারে, তবে: পি

#!/bin/bash

i=0

while read line
do
    if [ "${line:0:13}" == '<color name="' ]
    then
        a_keys[$i]="${line:13}"
        a_keys[$i]="${a_keys[$i]%%\"*}"
        a_values[$i]="$line"
        i=$((i+1))
    fi
done < a.xml

i=0

while read line
do
    if [ "${line:0:13}" == '<color name="' ]
    then
        b_keys[$i]="${line:13}"
        b_keys[$i]="${b_keys[$i]%%\"*}"
        b_values[$i]="$line"
        i=$((i+1))
    fi
done < b.xml

echo "<resources>"

i=0

for akey in "${a_keys[@]}"
do
    print=1

    for bkey in "${b_keys[@]}"
    do
        if [ "$akey" == "$bkey" ]
        then
            print=0
            break
        fi
    done

    if [ $print == 1 ]
    then
        echo "  ${a_values[$i]}"
    fi

    i=$(($i+1))
done

for value in "${b_values[@]}"
do
    echo "  $value"
done

echo "</resources>"

0

ঠিক আছে, দ্বিতীয় চেষ্টা করুন, এখন পার্ল (ইন না উত্পাদনের গুণমান, কোন পরীক্ষণ!):

#!/usr/bin/perl

open(A, "a.xml");

while(<A>) {
  next if(m;^\<resource\>$;);
  next if(m;^\<\/resource\>$;);
  ($name, $value) = m;^\s*\<color\s+name\s*\=\s*\"([^"]+)\"\>([^<]+)\<\/color\>$;;
  $nv{$name} = $value if $name;
}

close(A);

open(B, "b.xml");

while(<B>) {
  next if(m;^\<resource\>$;);
  next if(m;^\<\/resource\>$;);
  ($name, $value) = m;^\s*\<color\s+name\s*\=\*\"([^"]+)\"\>([^<]+)\<\/color\>$;;
  $nv{$name} = $value if $name;
}

close(B);

print "<resource>\n";
foreach (keys(%nv)) {
    print "   <color name=\"$_\">$nv{$_}</color>\n";
}
print "</resource>\n";

0

আর একটি, কাটা এবং গ্রেপ ব্যবহার করে ... (আর্গুমেন্ট হিসাবে a.xML b.xML নেয়)

#!/bin/bash

zap='"('"`grep '<color' "$2" | cut -d '"' -f 2 | tr '\n' '|'`"'")'
echo "<resources>"
grep '<color' "$1" | grep -E -v "$zap"
grep '<color' "$2"
echo "</resources>"

echoডিফল্ট ক্রিয়া হয়, তাই xargs echoঅতিরিক্ত অতিরিক্ত। আপনি কেবল tr '\n' '|'যাইহোক না কেন?
ট্রিপলি

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