วิธีเปรียบเทียบสองไฟล์


83

ดังนั้นโดยทั่วไปสิ่งที่ฉันต้องการทำคือเปรียบเทียบไฟล์สองไฟล์ต่อบรรทัดคอลัมน์ 2 ฉันจะทำสิ่งนี้ได้อย่างไร

File_1.txt:

User1 US
User2 US
User3 US

File_2.txt:

User1 US
User2 US
User3 NG

output_file:

User3 has changed

11
ใช้diff "File_1.txt" "File_2.txt"
Pandya

นอกจากนี้โปรดไปที่: askubuntu.com/q/12473
Pandya

คำตอบ:


92

มองเข้าไปในdiffคำสั่ง มันเป็นเครื่องมือที่ดีและคุณสามารถอ่านได้ทั้งหมดโดยพิมพ์ man diffลงในเทอร์มินัลของคุณ

คำสั่งที่คุณต้องการจะทำคือdiff File_1.txt File_2.txtสิ่งที่จะให้ความแตกต่างระหว่างทั้งสองและควรมีลักษณะดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ข้อความสั้น ๆ เกี่ยวกับการอ่านเอาต์พุตจากคำสั่งที่สาม: 'ลูกศร' ( <และ>) หมายถึงสิ่งที่มีค่าของบรรทัดอยู่ในไฟล์ด้านซ้าย ( <) เทียบกับไฟล์ด้านขวา ( >) กับไฟล์ด้านซ้ายเป็นไฟล์ที่คุณป้อน ก่อนในบรรทัดคำสั่งในกรณีนี้File_1.txt

นอกจากนี้คุณอาจสังเกตเห็นคำสั่งที่ 4 คือdiff ... | tee Output_Fileสิ่งนี้จะทำให้ท่อผลลัพธ์จากdiffในtee, จากนั้นใส่ผลลัพธ์ที่เป็นไฟล์เพื่อให้คุณสามารถบันทึกไว้ในภายหลังหากคุณไม่ต้องการที่จะดูมันทั้งหมดบนคอนโซลขวาที่สอง


สามารถทำไฟล์อื่น ๆ (เช่นรูปภาพ) ได้หรือไม่? หรือมันถูก จำกัด อยู่แค่เอกสาร?
Gregory Opera

2
เท่าที่ฉันรู้มัน จำกัด อยู่ที่ไฟล์ข้อความ รหัสจะใช้งานได้เนื่องจากเป็นข้อความหลัก แต่ไฟล์ไบนารี่ใด ๆ (รูปภาพใด) จะได้รับขยะ คุณสามารถเปรียบเทียบเพื่อดูว่าพวกเขาเหมือนกันหรือไม่โดยการทำ: diff file1 file2 -s. นี่คือตัวอย่าง: imgur.com/ShrQx9x
Mitch

มีวิธีการ colorize ผลลัพธ์หรือไม่ ฉันต้องการเก็บไว้เป็น CLI เท่านั้น แต่มีมากกว่านี้ ... สัมผัสของมนุษย์
Lazar Ljubenović

36

หรือคุณสามารถใช้Meld Diff

Meld ช่วยให้คุณเปรียบเทียบไฟล์ไดเรกทอรีและโครงการที่ควบคุมเวอร์ชัน มันมีการเปรียบเทียบสองทางและสามทางของทั้งไฟล์และไดเรกทอรีและสนับสนุนระบบควบคุมเวอร์ชันยอดนิยมหลายระบบ

ติดตั้งโดยใช้:

sudo apt-get install meld

ตัวอย่างของคุณ:

ป้อนคำอธิบายรูปภาพที่นี่

เปรียบเทียบไดเรกทอรี:

ป้อนคำอธิบายรูปภาพที่นี่

ตัวอย่างที่มีข้อความเต็ม:

ป้อนคำอธิบายรูปภาพที่นี่


18

คุณสามารถใช้vimdiff

ตัวอย่าง:

vimdiff  file1  file2

1
อันนี้มีสี
Jake Toronto

นี้ช่วยให้ฉันเป็นมันแสดงให้เห็นเส้นไฟล์แรกของฉันสิ้นสุดอยู่ในหนึ่งและสองในdos unix
LoMaPh

13

FWIW ฉันชอบสิ่งที่ฉันได้รับจากเอาท์พุทแบบเคียงข้างกัน

diff -y -W 120 File_1.txt File_2.txt

จะให้อะไรเช่น:

User1 US                            User1 US
User2 US                            User2 US
User3 US                          | User3 NG

10

คุณสามารถใช้คำสั่งcmp:

cmp -b "File_1.txt" "File_2.txt"

การส่งออกจะเป็น

a b differ: byte 25, line 3 is 125 U 116 N

cmpเร็วกว่ามากdiffหากคุณต้องการเพียงแค่ส่งคืนรหัส
stevesliva

8

Meldเป็นเครื่องมือที่ยอดเยี่ยมจริงๆ แต่คุณยังสามารถใช้diffuseเพื่อเปรียบเทียบภาพสองไฟล์:

diffuse file1.txt file2.txt

ป้อนคำอธิบายรูปภาพที่นี่


7

Litteraly เกาะติดกับคำถาม (file1, file2, outputfile พร้อมข้อความ "เปลี่ยนไปแล้ว") สคริปต์ด้านล่างนี้ใช้งานได้

คัดลอกสคริปต์ลงในไฟล์ว่างเปล่าบันทึกเป็นcompare.pyทำให้สามารถเรียกใช้งานได้โดยใช้คำสั่ง:

/path/to/compare.py <file1> <file2> <outputfile>

สคริปต์:

#!/usr/bin/env python

import sys
file1 = sys.argv[1]; file2 = sys.argv[2]; outfile = sys.argv[3]

def readfile(file):
    with open(file) as compare:
        return [item.replace("\n", "").split(" ") for item in compare.readlines()]

data1 = readfile(file1); data2 = readfile(file2)
mismatch = [item[0] for item in data1 if not item in data2]

with open(outfile, "wt") as out:
    for line in mismatch:
        out.write(line+" has changed"+"\n")

ด้วยสองบรรทัดพิเศษคุณสามารถทำให้มันพิมพ์ไปยัง outputfile หรือเทอร์มินัลขึ้นอยู่กับว่ามีการกำหนด outputfile:

หากต้องการพิมพ์เป็นไฟล์:

/path/to/compare.py <file1> <file2> <outputfile>

หากต้องการพิมพ์ไปที่หน้าต่างเทอร์มินัล:

/path/to/compare.py <file1> <file2> 

สคริปต์:

#!/usr/bin/env python

import sys

file1 = sys.argv[1]; file2 = sys.argv[2]
try:
    outfile = sys.argv[3]
except IndexError:
    outfile = None

def readfile(file):
    with open(file) as compare:
        return [item.replace("\n", "").split(" ") for item in compare.readlines()]

data1 = readfile(file1); data2 = readfile(file2)
mismatch = [item[0] for item in data1 if not item in data2]

if outfile != None:
        with open(outfile, "wt") as out:
            for line in mismatch:
                out.write(line+" has changed"+"\n")
else:
    for line in mismatch:
        print line+" has changed"

4

วิธีที่ง่ายคือใช้colordiffซึ่งทำหน้าที่เหมือนdiffแต่ให้สีของเอาต์พุต สิ่งนี้มีประโยชน์มากสำหรับการอ่านที่ต่างกัน ใช้ตัวอย่างของคุณ

$ colordiff -u File_1.txt File_2.txt
--- File_1.txt  2016-12-24 17:59:17.409490554 -0500
+++ File_2.txt  2016-12-24 18:00:06.666719659 -0500
@@ -1,3 +1,3 @@
 User1 US
 User2 US
-User3 US
+User3 NG

โดยที่uตัวเลือกนั้นให้ diff แบบรวม นี่คือลักษณะที่ต่างของ colorized:

ป้อนคำอธิบายรูปภาพที่นี่

ติดตั้งโดยการเรียกใช้colordiffsudo apt-get install colordiff


1
หากคุณต้องการสีฉันพบ diff ที่สร้างขึ้นในกลุ่มเพื่อใช้งานง่ายจริง ๆ ตามคำตอบของ Mr.S
thomasrutter

2

คำตอบเพิ่มเติม

หากไม่จำเป็นต้องทราบว่าส่วนใดของไฟล์ที่แตกต่างกันคุณสามารถใช้การตรวจสอบไฟล์ มีหลายวิธีที่จะทำที่ใช้หรือmd5sum sha256sumโดยพื้นฐานแล้วแต่ละไฟล์จะแสดงสตริงที่แฮชเนื้อหาไฟล์ หากทั้งสองไฟล์เหมือนกันแฮก็จะเหมือนกัน มักใช้เมื่อคุณดาวน์โหลดซอฟต์แวร์เช่นอิมเมจ iso การติดตั้ง Ubuntu พวกเขามักจะใช้สำหรับการตรวจสอบความสมบูรณ์ของเนื้อหาที่ดาวน์โหลด

พิจารณาสคริปต์ด้านล่างซึ่งคุณสามารถให้สองไฟล์เป็นอาร์กิวเมนต์และไฟล์จะบอกคุณว่าเหมือนกันหรือไม่

#!/bin/bash

# Check if both files exist  
if ! [ -e "$1"  ];
then
    printf "%s doesn't exist\n" "$1"
    exit 2
elif ! [ -e "$2" ]
then
    printf "%s doesn't exist\n" "$2"
    exit 2
fi

# Get checksums of eithe file
file1_sha=$( sha256sum "$1" | awk '{print $1}')
file2_sha=$( sha256sum "$2" | awk '{print $1}')

# Compare the checksums
if [ "x$file1_sha" = "x$file2_sha" ]
then
    printf "Files %s and %s are the same\n" "$1" "$2"
    exit 0
else
    printf "Files %s and %s are different\n" "$1" "$2"
    exit 1
fi

วิ่งตัวอย่าง:

$ ./compare_files.sh /etc/passwd ./passwd_copy.txt                                                                
Files /etc/passwd and ./passwd_copy.txt are the same
$ echo $?
0
$ ./compare_files.sh /etc/passwd /etc/default/grub                                                                
Files /etc/passwd and /etc/default/grub are different
$ echo $?
1

คำตอบที่เก่ากว่า

นอกจากนี้ยังมีcommคำสั่งซึ่งเปรียบเทียบสองไฟล์ที่เรียงลำดับและให้เอาต์พุตใน 3 colums: คอลัมน์ 1 สำหรับรายการที่ไม่ซ้ำกับไฟล์ # 1, คอลัมน์ 2 สำหรับรายการที่ไม่ซ้ำกับไฟล์ # 2 และคอลัมน์ 3 สำหรับรายการที่อยู่ในไฟล์ทั้งสอง

ในการยับยั้งคอลัมน์ใดคอลัมน์หนึ่งคุณสามารถใช้สวิตช์ -1, -2 และ -3 การใช้ -3 จะแสดงเส้นที่แตกต่างกัน

ร้องคุณสามารถดูภาพหน้าจอของคำสั่งในการดำเนินการ

ป้อนคำอธิบายรูปภาพที่นี่

มีข้อกำหนดเพียงข้อเดียว - ไฟล์จะต้องเรียงลำดับเพื่อทำการเปรียบเทียบอย่างถูกต้อง sortสามารถใช้คำสั่งเพื่อจุดประสงค์นั้นได้ ร้องเป็นภาพหน้าจออื่นที่ไฟล์จะถูกจัดเรียงและเปรียบเทียบแล้ว บรรทัดที่เริ่มต้นจากด้านซ้ายไปยัง File_1 เท่านั้นบรรทัดที่เริ่มต้นในคอลัมน์ 2 เป็นของ File_2 เท่านั้น

ป้อนคำอธิบายรูปภาพที่นี่


@DavidFoerster มันยากที่จะแก้ไขบนมือถือ :) ทำตอนนี้แม้ว่า
Sergiy Kolodyazhnyy

2

ติดตั้งคอมไพล์และใช้

$ git diff filename1 filename2

และคุณจะได้ผลลัพธ์ในรูปแบบสีที่สวยงาม

การติดตั้งGit

$ apt-get update
$ apt-get install git-core

2

colcmp.sh

เปรียบเทียบชื่อ / คู่ค่าใน 2 name value\nไฟล์ในรูปแบบ เขียนnameไปที่Output_fileหากมีการเปลี่ยนแปลง ต้องทุบตี v4 + สำหรับเชื่อมโยงอาร์เรย์

การใช้

$ ./colcmp.sh File_1.txt File_2.txt
User3 changed from 'US' to 'NG'
no change: User1,User2

output_file

$ cat Output_File
User3 has changed

แหล่งที่มา (colcmp.sh)

cmp -s "$1" "$2"
case "$?" in
    0)
        echo "" > Output_File
        echo "files are identical"
        ;;
    1)
        echo "" > Output_File
        cp "$1" ~/.colcmp.array1.tmp.sh
        sed -i -E "s/([^A-Za-z0-9 ])/\\\\\\1/g" ~/.colcmp.array1.tmp.sh
        sed -i -E "s/^(.*)$/#\\1/" ~/.colcmp.array1.tmp.sh
        sed -i -E "s/^#\\s*(\\S+)\\s+(\\S.*?)\\s*\$/A1\\[\\1\\]=\"\\2\"/" ~/.colcmp.array1.tmp.sh
        chmod 755 ~/.colcmp.array1.tmp.sh
        declare -A A1
        source ~/.colcmp.array1.tmp.sh

        cp "$2" ~/.colcmp.array2.tmp.sh
        sed -i -E "s/([^A-Za-z0-9 ])/\\\\\\1/g" ~/.colcmp.array2.tmp.sh
        sed -i -E "s/^(.*)$/#\\1/" ~/.colcmp.array2.tmp.sh
        sed -i -E "s/^#\\s*(\\S+)\\s+(\\S.*?)\\s*\$/A2\\[\\1\\]=\"\\2\"/" ~/.colcmp.array2.tmp.sh
        chmod 755 ~/.colcmp.array2.tmp.sh
        declare -A A2
        source ~/.colcmp.array2.tmp.sh

        USERSWHODIDNOTCHANGE=
        for i in "${!A1[@]}"; do
            if [ "${A2[$i]+x}" = "" ]; then
                echo "$i was removed"
                echo "$i has changed" > Output_File
            fi
        done
        for i in "${!A2[@]}"; do
            if [ "${A1[$i]+x}" = "" ]; then
                echo "$i was added as '${A2[$i]}'"
                echo "$i has changed" > Output_File
            elif [ "${A1[$i]}" != "${A2[$i]}" ]; then
                echo "$i changed from '${A1[$i]}' to '${A2[$i]}'"
                echo "$i has changed" > Output_File
            else
                if [ x$USERSWHODIDNOTCHANGE != x ]; then
                    USERSWHODIDNOTCHANGE=",$USERSWHODIDNOTCHANGE"
                fi
                USERSWHODIDNOTCHANGE="$i$USERSWHODIDNOTCHANGE"
            fi
        done
        if [ x$USERSWHODIDNOTCHANGE != x ]; then
            echo "no change: $USERSWHODIDNOTCHANGE"
        fi
        ;;
    *)
        echo "error: file not found, access denied, etc..."
        echo "usage: ./colcmp.sh File_1.txt File_2.txt"
        ;;
esac

การอธิบาย

การแบ่งรหัสและความหมายของมันให้ดีที่สุดเพื่อความเข้าใจของฉัน ฉันยินดีต้อนรับการแก้ไขและข้อเสนอแนะ

เปรียบเทียบไฟล์พื้นฐาน

cmp -s "$1" "$2"
case "$?" in
    0)
        # match
        ;;
    1)
        # compare
        ;;
    *)
        # error
        ;;
esac

cmpจะตั้งค่าของ $? เป็นดังต่อไปนี้ :

  • 0 = ไฟล์ตรงกัน
  • 1 = ไฟล์ต่างกัน
  • 2 = ข้อผิดพลาด

ฉันเลือกที่จะใช้กรณี ..คำสั่งesacเพื่อประเมิน$? เพราะมูลค่าของ$? การเปลี่ยนแปลงหลังจากทุกคำสั่งรวมถึงการทดสอบ ([)

หรือฉันอาจใช้ตัวแปรเพื่อเก็บค่าของ$? :

cmp -s "$1" "$2"
CMPRESULT=$?
if [ $CMPRESULT -eq 0 ]; then
    # match
elif [ $CMPRESULT -eq 1 ]; then
    # compare
else
    # error
fi

ข้างต้นทำสิ่งเดียวกันกับคำสั่งกรณี IDK ที่ฉันชอบดีกว่า

เคลียร์เอาต์พุต

        echo "" > Output_File

ด้านบนจะล้างไฟล์เอาต์พุตดังนั้นหากไม่มีผู้ใช้เปลี่ยนไฟล์เอาต์พุตจะว่างเปล่า

ฉันทำเช่นนี้ในงบกรณีเพื่อให้Output_fileยังคงไม่เปลี่ยนแปลงข้อผิดพลาด

คัดลอกไฟล์ผู้ใช้ไปยัง Shell Script

        cp "$1" ~/.colcmp.arrays.tmp.sh

ด้านบนคัดลอกFile_1.txtไปยัง dir บ้านของผู้ใช้ปัจจุบัน

ตัวอย่างเช่นถ้าผู้ใช้ปัจจุบันคือ john สิ่งที่กล่าวมาข้างต้นจะเหมือนกับcp "File_1.txt" /home/john/.colcmp.arrays.tmp.sh

หลบหนีตัวละครพิเศษ

โดยพื้นฐานแล้วฉันเป็นคนหวาดระแวง ฉันรู้ว่าตัวละครเหล่านี้อาจมีความหมายพิเศษหรือรันโปรแกรมภายนอกเมื่อทำงานในสคริปต์เป็นส่วนหนึ่งของการกำหนดตัวแปร:

  • `- back-tick - รันโปรแกรมและเอาต์พุตราวกับว่าเอาต์พุตเป็นส่วนหนึ่งของสคริปต์ของคุณ
  • $ - เครื่องหมายดอลลาร์ - มักจะนำหน้าตัวแปร
  • $ {} - อนุญาตให้มีการทดแทนตัวแปรที่ซับซ้อนมากขึ้น
  • $ () - idk สิ่งนี้ทำ แต่ฉันคิดว่ามันสามารถเรียกใช้รหัส

สิ่งที่ฉันไม่รู้คือเท่าไหร่ที่ฉันไม่รู้เกี่ยวกับการทุบตี ฉันไม่รู้ว่าตัวละครอื่น ๆ อาจมีความหมายพิเศษ แต่ฉันต้องการหลบหนีพวกเขาทั้งหมดด้วยแบ็กสแลช:

        sed -i -E "s/([^A-Za-z0-9 ])/\\\\\\1/g" ~/.colcmp.array1.tmp.sh

sedสามารถทำมากขึ้นกว่าที่จับคู่รูปแบบการแสดงผลปกติ รูปแบบสคริปต์ "s / (ค้นหา) / (แทนที่) /"ทำการจับคู่รูปแบบโดยเฉพาะ

"s / (ค้นหา) / (แทนที่) / (ปรับเปลี่ยน)"

ในภาษาอังกฤษ:จับเครื่องหมายวรรคตอนหรืออักขระพิเศษใด ๆ เป็นกลุ่ม caputure 1 (\\ 1)

  • (แทนที่) = \\\\\\ 1

ในภาษาอังกฤษ:นำหน้าอักขระพิเศษทั้งหมดด้วยแบ็กสแลช

  • (ตัวดัดแปลง) = g
    • g = แทนที่ทั่วโลก

ในภาษาอังกฤษ:หากพบมากกว่าหนึ่งการแข่งขันในบรรทัดเดียวกันให้แทนที่พวกเขาทั้งหมด

ความคิดเห็นออกสคริปต์ทั้งหมด

        sed -i -E "s/^(.*)$/#\\1/" ~/.colcmp.arrays.tmp.sh

ด้านบนใช้นิพจน์ทั่วไปเพื่อใส่คำนำหน้าทุกบรรทัดของ~ / .colcmp.arrays.tmp.shด้วยอักขระความคิดเห็น bash ( # ) ฉันทำเช่นนี้เพราะต่อมาผมตั้งใจที่จะดำเนินการ~ / .colcmp.arrays.tmp.shใช้แหล่งที่มาของคำสั่งและเพราะผมไม่ทราบว่ารูปแบบทั้งหมดของFile_1.txt

ฉันไม่ต้องการเรียกใช้รหัสโดยอำเภอใจ ฉันไม่คิดว่าจะมีใครทำ

"s / (ค้นหา) / (แทนที่) /"

ในภาษาอังกฤษ:จับแต่ละบรรทัดเป็นกลุ่มการเย็บ 1 (\\ 1)

  • (แทนที่) = # \\ 1
    • # = ตัวอักษรตามตัวอักษร (#) เช่นสัญลักษณ์ปอนด์หรือแฮช
    • \\ 1 = กลุ่มจับภาพ 1

ในภาษาอังกฤษ:แทนที่แต่ละบรรทัดด้วยสัญลักษณ์ปอนด์ตามด้วยบรรทัดที่ถูกแทนที่

แปลงค่าผู้ใช้เป็น A1 [ผู้ใช้] = "ค่า"

        sed -i -E "s/^#\\s*(\\S+)\\s+(\\S.*?)\\s*\$/A1\\[\\1\\]=\"\\2\"/" ~/.colcmp.arrays.tmp.sh

ด้านบนเป็นหัวใจของสคริปต์นี้

  • แปลงสิ่งนี้: #User1 US
    • สำหรับสิ่งนี้: A1[User1]="US"
    • หรือนี่: A2[User1]="US"(สำหรับไฟล์ที่ 2)

"s / (ค้นหา) / (แทนที่) /"

เป็นภาษาอังกฤษ:

  • ต้องการ แต่ไม่สนใจอักขระความคิดเห็นชั้นนำ (#)
  • ละเว้นช่องว่างนำหน้า
  • จับคำแรกเป็นกลุ่มที่ 1 (\\ 1)
  • ต้องการช่องว่าง (หรือแท็บหรือช่องว่าง)
    • ที่จะถูกแทนที่ด้วยเครื่องหมายเท่ากับเพราะ
    • มันไม่ได้เป็นส่วนหนึ่งของกลุ่มการจับภาพใด ๆ และเพราะ
    • รูปแบบ (แทนที่) ใส่เครื่องหมายเท่ากับระหว่างกลุ่มการดักจับ 1 และกลุ่มการดักจับ 2
  • จับส่วนที่เหลือของบรรทัดเป็นกลุ่มการจับภาพ 2

  • (แทนที่) = A1 \\ [\\ 1 \\] = \ "\\ 2 \"

    • A1 \\ [- ตัวอักษรตัวอักษรA1[เพื่อเริ่มการกำหนดอาร์เรย์ในอาร์เรย์ที่เรียกว่าA1
    • \\ 1 = กลุ่มการดักจับ 1 - ซึ่งไม่รวมแฮชนำหน้า (#) และไม่รวมช่องว่างนำหน้า - ในกรณีนี้กลุ่มการดักจับ 1 จะถูกใช้เพื่อตั้งชื่อของคู่ชื่อ / ค่าในอาเรย์ของ bash
    • \\] = \ "= ตัวอักษร ]="
      • ]= ปิดการกำหนดอาร์เรย์เช่นA1[User1 ]="US"
      • = = ผู้ประกอบการที่ได้รับมอบหมายเช่นตัวแปร = ค่า
      • " = มูลค่าอ้างอิงเพื่อจับช่องว่าง ... แม้ว่าตอนนี้ฉันคิดเกี่ยวกับมันแล้วมันจะง่ายกว่าถ้าให้โค้ดด้านบนนั้นแบ็กสแลชทุกอย่างเป็นอักขระช่องว่างแบ็กสแลช
    • \\ 1 = กลุ่มการจับภาพ 2 - ในกรณีนี้คือค่าของคู่ชื่อ / ค่า
    • "= ปิดการเสนอราคาเพื่อจับช่องว่าง

เป็นภาษาอังกฤษ:แทนที่แต่ละบรรทัดในรูปแบบ#name valueด้วยตัวดำเนินการกำหนดอาร์เรย์ในรูปแบบA1[name]="value"

ทำให้ปฏิบัติการได้

        chmod 755 ~/.colcmp.arrays.tmp.sh

ด้านบนใช้chmodเพื่อทำให้ไฟล์สคริปต์ของอาร์เรย์ทำงานได้

ฉันไม่แน่ใจว่าจำเป็นหรือไม่

ประกาศ Array Associative Array (bash v4 +)

        declare -A A1

-A ทุนบ่งชี้ว่าตัวแปรประกาศจะเชื่อมโยงอาร์เรย์

นี่คือเหตุผลที่สคริปต์ต้องการ bash v4 หรือสูงกว่า

ดำเนินการสคริปต์การกำหนดค่าอาร์เรย์ของเรา

        source ~/.colcmp.arrays.tmp.sh

เรามีอยู่แล้ว:

  • แปลงไฟล์ของเราจากบรรทัดUser valueถึงเป็นA1[User]="value",
  • ทำให้มันปฏิบัติได้ (อาจ) และ
  • ประกาศ A1 เป็นอาเรย์แบบเชื่อมโยง ...

ด้านบนเรามาสคริปต์เพื่อเรียกใช้ในเปลือกปัจจุบัน เราทำสิ่งนี้เพื่อให้เราสามารถเก็บค่าตัวแปรที่กำหนดโดยสคริปต์ หากคุณรันสคริปต์โดยตรงมันจะสร้างเชลล์ใหม่และค่าตัวแปรจะหายไปเมื่อเชลล์ใหม่ออกหรืออย่างน้อยนั่นคือความเข้าใจของฉัน

นี่ควรจะเป็นฟังก์ชั่น

        cp "$2" ~/.colcmp.array2.tmp.sh
        sed -i -E "s/([^A-Za-z0-9 ])/\\\\\\1/g" ~/.colcmp.array2.tmp.sh
        sed -i -E "s/^(.*)$/#\\1/" ~/.colcmp.array2.tmp.sh
        sed -i -E "s/^#\\s*(\\S+)\\s+(\\S.*?)\\s*\$/A2\\[\\1\\]=\"\\2\"/" ~/.colcmp.array2.tmp.sh
        chmod 755 ~/.colcmp.array2.tmp.sh
        declare -A A2
        source ~/.colcmp.array2.tmp.sh

เราทำสิ่งเดียวกันสำหรับ$ 1และA1ว่าเราทำเพื่อ$ 2และA2 มันควรจะเป็นฟังก์ชั่น ฉันคิดว่า ณ จุดนี้สคริปต์นี้มีความสับสนมากพอและได้ผลฉันจึงไม่ควรแก้ไข

ตรวจจับผู้ใช้ลบออก

        for i in "${!A1[@]}"; do
            # check for users removed
        done

ด้านบนวนซ้ำผ่านแป้นอาเรย์แบบเชื่อมโยง

            if [ "${A2[$i]+x}" = "" ]; then

ด้านบนใช้การทดแทนตัวแปรเพื่อตรวจสอบความแตกต่างระหว่างค่าที่ไม่ได้ตั้งค่าเทียบกับตัวแปรที่ได้รับการตั้งค่าอย่างชัดเจนเป็นสตริงที่มีความยาวเป็นศูนย์

เห็นได้ชัดว่ามีหลายวิธีที่จะดูว่าตัวแปรที่ได้รับการตั้ง ฉันเลือกอันที่มีคะแนนมากที่สุด

                echo "$i has changed" > Output_File

ด้านบนเพิ่มผู้ใช้$ iลงในOutput_File

ตรวจจับผู้ใช้ที่เพิ่มหรือเปลี่ยน

        USERSWHODIDNOTCHANGE=

ล้างตัวแปรข้างต้นเพื่อให้เราสามารถติดตามผู้ใช้ที่ไม่เปลี่ยนแปลง

        for i in "${!A2[@]}"; do
            # detect users added, changed and not changed
        done

ด้านบนวนซ้ำผ่านแป้นอาเรย์แบบเชื่อมโยง

            if ! [ "${A1[$i]+x}" != "" ]; then

ข้างต้นใช้แทนค่าตัวแปรที่จะดูว่าตัวแปรที่ได้รับการตั้ง

                echo "$i was added as '${A2[$i]}'"

เพราะ$ iเป็นกุญแจสำคัญในอาร์เรย์ (ชื่อผู้ใช้) $ A2 [$ i] ควรกลับค่าที่เกี่ยวข้องกับผู้ใช้ปัจจุบันจากFile_2.txt

ตัวอย่างเช่นถ้า$ iคือUser1ข้อความด้านบนจะอ่านว่าเป็น$ {A2 [User1]}

                echo "$i has changed" > Output_File

ด้านบนเพิ่มผู้ใช้$ iลงในOutput_File

            elif [ "${A1[$i]}" != "${A2[$i]}" ]; then

เพราะ$ iเป็นกุญแจสำคัญในอาร์เรย์ (ชื่อผู้ใช้) $ A1 [$ i] ควรกลับค่าที่เกี่ยวข้องกับผู้ใช้ปัจจุบันจากFile_1.txtและ $ A2 [$ i] ควรกลับค่าจากFile_2.txt

เปรียบเทียบค่าที่เกี่ยวข้องสำหรับผู้ใช้$ iจากทั้งสองไฟล์

                echo "$i has changed" > Output_File

ด้านบนเพิ่มผู้ใช้$ iลงในOutput_File

                if [ x$USERSWHODIDNOTCHANGE != x ]; then
                    USERSWHODIDNOTCHANGE=",$USERSWHODIDNOTCHANGE"
                fi
                USERSWHODIDNOTCHANGE="$i$USERSWHODIDNOTCHANGE"

ด้านบนสร้างรายการที่คั่นด้วยเครื่องหมายจุลภาคของผู้ใช้ที่ไม่เปลี่ยนแปลง โปรดทราบว่าไม่มีช่องว่างในรายการมิฉะนั้นจะต้องมีการเสนอการตรวจสอบครั้งต่อไป

        if [ x$USERSWHODIDNOTCHANGE != x ]; then
            echo "no change: $USERSWHODIDNOTCHANGE"
        fi

ดังกล่าวข้างต้นรายงานค่าของ$ USERSWHODIDNOTCHANGEแต่ถ้ามีค่าใน$ USERSWHODIDNOTCHANGE วิธีที่เขียนนี้$ USERSWHODIDNOTCHANGEต้องไม่มีช่องว่างใด ๆ หากต้องการช่องว่างสามารถเขียนใหม่ด้านบนได้ดังนี้:

        if [ "$USERSWHODIDNOTCHANGE" != "" ]; then
            echo "no change: $USERSWHODIDNOTCHANGE"
        fi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.