मैंने अभी-अभी लिनक्स शेल स्क्रिप्टिंग सीखना शुरू किया है। मुझे संस्करण नियंत्रण उदाहरण के लिए लिनक्स शेल स्क्रिप्टिंग में इन दो फाइलों की तुलना करनी है:

File1.txt

  • 275caa62391ff4f3096b1e8a4975de40 सेब
  • awd6s54g64h6se4h6se45wahae654j6 गेंद
  • e4rby1s6y4653a46h153a41bqwa54tvi बिल्ली
  • r53aghe4354hr35a4hr65a46eeh5j45ro अरंडी

File2.txt

  • 275caa62391ff4f3096b1e8a4975de40 सेब
  • js65fg4a64zgr65f4w65ea465fa65gh7 गेंद
  • wroghah4a65ejdtse5z4g6sa7H658aw7 मोमबत्ती
  • wagjh54hr5ae454zrwrh354aha4564re अरंडी

इस टेक्स्ट फ़ाइलों को नए जोड़े में कैसे सॉर्ट करें (एक जो फ़ाइल 2 में जोड़ा गया है लेकिन फ़ाइल 1 में नहीं है), हटा दिया गया है (जिसे फ़ाइल 2 में हटा दिया गया है लेकिन फ़ाइल 1 में नहीं) और बदली गई फ़ाइलें (एक ही नाम लेकिन अलग चेकसम है) ? मैंने diff , bcompare , vimdiff का उपयोग करने का प्रयास किया लेकिन मुझे टेक्स्ट फ़ाइल के रूप में उचित आउटपुट नहीं मिल रहा है।

अग्रिम में धन्यवाद

1
karkator 20 जिंदा 2020, 13:10
भाग 3 के लिए (एक ही नाम लेकिन अलग चेकसम है) --- md5sum -c file1 file2 आज़माएं
 – 
Avinash Yadav
20 जिंदा 2020, 13:35
भाग 3 के लिए वह पाठ के पहले भाग की बात कर रहा है
 – 
bob dylan
20 जिंदा 2020, 18:38

2 जवाब

मुझे नहीं पता कि ऐसा कोई आदेश मौजूद है, लेकिन मैंने आपको बैश में एक छँटाई तंत्र लिखने की स्वतंत्रता ली है। हालांकि यह अनुकूलित है, मेरा सुझाव है कि आप इसे अपनी पसंद की भाषा में फिर से बनाएँ।

#! /bin/bash

# Sets the array delimiter to a newline
IFS=$'\n'

# If $1 is empty, default to 'file1.txt'. Same for $2.
FILE1=${1:-file1.txt}
FILE2=${2:-file2.txt}

DELETED=()
ADDED=()
CHANGED=()

# Loop over array $1 and print content
function array_print {
        # -n creates a "pointer" to an array. This
        # way you can pass large arrays to functions.
        local -n array=$1
        echo "$1: "

        for i in "${array}"; do
                echo $i
        done
}

# This function loops over the entries in file_in and checks
# if they exist in file_tst. Unless doubles are found, a
# callback is executed.
function array_sort {
        local file_in="$1"
        local file_tst="$2"
        local callback=${3:-true}
        local -n arr0=$4
        local -n arr1=$5

        while read -r line; do

                tst_hash=$(grep -Eo '^[^ ]+' <<< "$line")
                tst_name=$(grep -Eo '[^ ]+$' <<< "$line")
                hit=$(grep $tst_name $file_tst)

                # If found, skip. Nothing is changed.
                [[ $hit != $line ]] || continue

                # Run callback
                $callback "$hit" "$line" arr0 arr1

        done < "$file_in"
}

# If tst is empty, line will be added to not_found. For file 1 this 
# means that file doesn't exist in file2, thus is deleted. Otherwise
# the file is changed.
function callback_file1 {
        local tst=$1
        local line=$2
        local -n not_found=$3
        local -n found=$4

        if [[ -z $tst ]]; then
                not_found+=($line)
        else
                found+=($line)
        fi
}

# If tst is empty, line will be added to not_found. For file 2 this
# means that file doesn't exist in file1, thus is added. Since the 
# callback for file 1 already filled all the changed files, we do 
# nothing with the fourth parameter.
function callback_file2 {
        local tst=$1
        local line=$2
        local -n not_found=$3

        if [[ -z $tst ]]; then
                not_found+=($line)
        fi
}

array_sort "$FILE1" "$FILE2" callback_file1 DELETED CHANGED 
array_sort "$FILE2" "$FILE1" callback_file2 ADDED CHANGED 

array_print ADDED
array_print DELETED
array_print CHANGED
exit 0

चूंकि उपरोक्त कोड को समझना मुश्किल हो सकता है, इसलिए मैंने इसे लिखा है। मुझे उम्मीद है यह मदद करेगा :-)

while read -r line; do
       tst_hash=$(grep -Eo '^[^ ]+' <<< "$line")
       tst_name=$(grep -Eo '[^ ]+$' <<< "$line")
       hit=$(grep $tst_name $FILE2)

       # If found, skip. Nothing is changed.
       [[ $hit != $line ]] || continue

       # If name does not occur, it's deleted (exists in 
       # file1, but not in file2)
       if [[ -z $hit ]]; then
               DELETED+=($line)
       else
       # If name occurs, it's changed. Otherwise it would
       # not come here due to previous if-statement.
               CHANGED+=($line)
       fi
done < "$FILE1"

while read -r line; do
       tst_hash=$(grep -Eo '^[^ ]+' <<< "$line")
       tst_name=$(grep -Eo '[^ ]+$' <<< "$line")
       hit=$(grep $tst_name $FILE1)

       # If found, skip. Nothing is changed.
       [[ $hit != $line ]] || continue

       # If name does not occur, it's added. (exists in 
       # file2, but not in file1)
       if [[ -z $hit ]]; then
               ADDED+=($line)
       fi
done < "$FILE2"
0
Bayou 20 जिंदा 2020, 17:46
ऐसा लगता है कि यह बैश प्रोग्राम केवल चार लाइनों के लिए डेटा की तुलना करता है, मैं दो टेक्स्ट फाइलों की तुलना करना चाहता था जिनमें कई लाइनें हैं। इस कोड के लिए बहुत-बहुत धन्यवाद।
 – 
karkator
21 जिंदा 2020, 10:45
आप ऐसा क्यों सोचते हैं? डेटा फ़ाइल से लिया जाता है, फ़ाइल की लंबाई की परवाह किए बिना।
 – 
Bayou
21 जिंदा 2020, 12:05

फ़ाइलें जो केवल file1.txt में हैं:

 awk 'NR==FNR{a[$2];next} !($2 in a)' file2.txt file1.txt > only_in_file1.txt

फ़ाइलें जो केवल file2.txt में हैं:

 awk 'NR==FNR{a[$2];next} !($2 in a)' file1.txt file2.txt > only_in_file2.txt

फिर कुछ इस तरह का जवाब: अजीब दो फाइलों से कॉलम की तुलना करें, के मूल्यों को लागू करें एक और कॉलम

उदाहरण:

awk 'FNR==NR{a[$1]=$1;next}{print $0,a[$1]?a[$2]:"NA"}' file2.txt file1.txt  | grep NA | awk '{print $1,$2}' > md5sdiffer.txt

हालाँकि आपको यह बताना होगा कि आप इन्हें कैसे प्रस्तुत करना चाहते हैं।

अंतिम उदाहरण के बावजूद लूप करने का एक और शानदार तरीका हो सकता है (जैसा कि एनए के साथ खोजने और फिर फिर से फ़िल्टर करने के विपरीत), हालांकि यह अभी भी बंद होने के लिए पर्याप्त है

0
bob dylan 20 जिंदा 2020, 18:45