วิธีกระจายไฟล์โดยไม่คำนึงถึงความคิดเห็น (บรรทัดที่ขึ้นต้นด้วย #)


55

ฉันมีไฟล์กำหนดค่าสองไฟล์ต้นฉบับจากผู้จัดการแพ็กเกจและไฟล์ที่กำหนดเองที่แก้ไขด้วยตัวเอง ฉันได้เพิ่มความคิดเห็นเพื่ออธิบายพฤติกรรม

ฉันจะรันdiffไฟล์กำหนดค่าโดยข้ามความคิดเห็นได้อย่างไร บรรทัดความคิดเห็นถูกกำหนดโดย:

  • ช่องว่างนำหน้าตัวเลือก (แท็บและช่องว่าง)
  • เครื่องหมายแฮช ( #)
  • ตัวละครอื่น ๆ

(ที่ง่ายที่สุด) #.*การแสดงออกปกติข้ามความต้องการแรกจะเป็น ฉันลองตัวเลือก--ignore-matching-lines=RE( -I RE) ของ GNU diff 3.0 แต่ฉันไม่สามารถทำงานกับ RE นั้นได้ ฉันยังพยายาม.*#.*และ.*\#.*ไม่มีโชค การวางบรรทัด ( Port 631) ตามตัวอักษรอย่างแท้จริงREไม่ตรงกับสิ่งใดเลยและไม่ช่วยให้วาง RE ระหว่างเครื่องหมายทับ

ตามที่แนะนำในregex แล้วรสชาติของเครื่องมือ“ diff” นั้นขาดไปหรือไม่? ฉันพยายามgrep -G:

grep -G '#.*' file

นี้ดูเหมือนว่าจะตรงกับความเห็น diff -I '#.*' file1 file2แต่มันไม่ทำงานสำหรับ

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


12
-Iตัวเลือกที่ทำให้เกิดการบล็อกที่จะละเลย แต่ถ้าทุกเส้นตรงกับ regexp ดังนั้นคุณสามารถเพิกเฉยต่อการเปลี่ยนแปลงความคิดเห็นอย่างเดียวได้ แต่ไม่ใช่การเปลี่ยนแปลงความคิดเห็นที่อยู่ใกล้กับการเปลี่ยนแปลงที่ไม่ใช่ความคิดเห็น
Gilles 'หยุดความชั่วร้าย'

@Gilles: ขอบคุณตอนนี้ฉันได้รับมันทำไมdiff -Iไม่ทำงานตามที่ฉันคาดไว้ ฉันอัปเดตคำตอบของฉันด้วยตัวอย่างที่อธิบายพฤติกรรมนี้ให้ฉันทราบ
Lekensteyn

คำตอบ:


49

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

บททดสอบ

มีสามไฟล์ที่เกี่ยวข้องในการทดสอบของฉัน:
ไฟล์test1:

    text

ไฟล์test2:

    text
    #comment

ไฟล์test3:

    changed text
    #comment

คำสั่ง:

$ # comparing files with comment-only changes
$ diff -u -I '#.*' test{1,2}
$ # comparing files with both comment and regular changes
$ diff -u -I '#.*' test{2,3}
--- test2       2011-07-20 16:38:59.717701430 +0200
+++ test3       2011-07-20 16:39:10.187701435 +0200
@@ -1,2 +1,2 @@
-text
+changed text
 #comment

ทางเลือกอื่น

เนื่องจากยังไม่มีคำตอบที่อธิบายวิธีใช้-Iตัวเลือกอย่างถูกต้องฉันจะให้ทางเลือกซึ่งใช้งานได้ใน bash shells:

diff -u -B <(grep -vE '^\s*(#|$)' test1)  <(grep -vE '^\s*(#|$)' test2)
  • diff -u - รวมต่างกัน
    • -B - ละเว้นบรรทัดว่าง
  • <(command)- คุณสมบัติทุบตีที่เรียกว่าการทดแทนกระบวนการซึ่งเปิดตัวอธิบายไฟล์สำหรับคำสั่งสิ่งนี้จะลบความต้องการไฟล์ชั่วคราว
  • grep - คำสั่งสำหรับการพิมพ์เส้น (ไม่) จับคู่รูปแบบ
    • -v - แสดงบรรทัดที่ไม่ตรงกัน
    • E - ใช้นิพจน์ทั่วไปแบบขยาย
    • '^\s*(#|$)' - นิพจน์ทั่วไปที่ตรงกับข้อคิดเห็นและบรรทัดว่าง
      • ^ - จับคู่จุดเริ่มต้นของบรรทัด
      • \s* - จับคู่ช่องว่าง (แท็บและช่องว่าง) หากมี
      • (#|$) ตรงกับเครื่องหมายแฮชหรือมิฉะนั้นจุดสิ้นสุดของบรรทัด

6

ลอง:

diff -b -I '^#' -I '^ #' file1 file2

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

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

เราสามารถอ่านได้ในdiffutilsคู่มือ:

อย่างไรก็ตาม-Iละเว้นการแทรกหรือลบบรรทัดที่มีการแสดงออกปกติเท่านั้นหากทุกบรรทัดที่เปลี่ยนแปลงในก้อนใหญ่ (ทุกการแทรกและการลบทุกครั้ง) ตรงกับการแสดงออกปกติ

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

ลักษณะการทำงานนี้จะมีการอธิบายอย่างดีจากarmel ที่นี่

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


2

หลังจากค้นหาในเว็บทางเลือกอื่นของ Lekensteyn เป็นวิธีที่ดีกว่าที่ฉันพบ

แต่ฉันต้องการใช้เอาท์พุท dif เป็นแพทช์ ... และมีปัญหาเพราะหมายเลขบรรทัดถูกบันทึกไว้เพราะ "grep -v"

ดังนั้นฉันจึงต้องการปรับปรุงบรรทัดคำสั่งนี้:

diff -u -B <(sed 's/^[[:blank:]]*#.*$/ /' file1)  <(sed 's/^[[:blank:]]*#.*$/ /' file2)

มันไม่สมบูรณ์แบบ แต่หมายเลขบรรทัดจะถูกเก็บไว้ในไฟล์แพทช์

อย่างไรก็ตามหากมีการเพิ่มบรรทัดใหม่แทนบรรทัดความคิดเห็น ... ความคิดเห็นจะสร้าง Hunk FAILED เมื่อทำการปะแก้เนื่องจากเราจะเห็นการร้อง

File test1:
  text
  #comment
  other text
File test2:
  text
  new line here
  #comment changed
  other text changed

ทดสอบตอนนี้คำสั่งของเรา

$ echo -e "#!/usr/bin/sed -f\ns/^[[:blank:]]*#.*$/ /" > outcom.sed
$ echo "diff -u -B <(./outcom.sed \$1)  <(./outcom.sed \$2)" > mydiff.sh
$ chmod +x mydiff.sh outcom.sed
$ ./mydiff.sh file1 file2 > file.dif
$ cat file.dif
--- /dev/fd/63  2014-08-23 10:05:08.000000000 +0200
+++ /dev/fd/62  2014-08-23 10:05:08.000000000 +0200
@@ -1,2 +1,3 @@
 text
+new line

-other text
+other text changed

/ dev / fd / 62 & / dev / fd / 63 เป็นไฟล์ที่สร้างขึ้นโดยการทดแทนกระบวนการ บรรทัดระหว่าง "+ new line" และ "-other text" คืออักขระช่องว่างเริ่มต้นที่กำหนดไว้ในนิพจน์ sed ของเราเพื่อแทนที่ความคิดเห็น

และตอนนี้สิ่งที่มาเมื่อเราใช้แพทช์นี้:

$ patch -p0 file1 < file.dif 
patching file file1
Hunk #1 FAILED at 1.
1 out of 1 hunk FAILED -- saving rejects to file file1.rej

วิธีแก้ไขคืออย่าใช้รูปแบบ diff แบบรวมโดยไม่มี -u

$ echo "diff -B <(./outcom.sed \$1)  <(./outcom.sed \$2)" > mydiff.sh
$ ./mydiff.sh file1 file2 > file.dif
$ cat file.dif
1a2
> new line
3c4
< other text
---
> other text changed
$ patch -p0 file1 < file.dif 
patching file file1
$ cat file1
text
new line
#comment
other text changed

ตอนนี้ไฟล์ทำงานไฟล์ปะ (โดยไม่มีการรับประกันผลลัพธ์ในกระบวนการ diff ที่ซับซ้อนมาก)


diff แบบรวมของคุณไม่สามารถใช้งานได้เนื่องจากความแตกต่างของบริบท คุณสามารถใช้diff -U0 one twoเพื่อปิดใช้งานบริบท สำหรับการปรับปรุงมีเครื่องมือมากมายที่อาจเหมาะสมกว่าเช่น kdiff3
Lekensteyn

ขอบคุณสำหรับ-U0ตัวเลือกในการปิดใช้งานบริบท หมายเหตุ: kdiff3 เป็นเครื่องมือกราฟิก ฉันต้องการเครื่องมืออัตโนมัติสำหรับจัดการคุณสมบัติการรวมคอมไพล์
syjust

vimdiffรองรับการผสานสามทางอาจคุ้มค่าที่จะดู
Lekensteyn

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

1

ฉันมักจะไม่สนใจความยุ่งเหยิงนี้โดย:

  • กำลังสร้างเวอร์ชันที่ไม่มีความคิดเห็นโดยการใช้grep -v "^#" | cat -sและการกระจายหรือ
  • ใช้vim -dเพื่อดูไฟล์ การเน้นไวยากรณ์จะช่วยในการแสดงความคิดเห็นกับความแตกต่างที่ไม่ใช่ความคิดเห็นค่อนข้างชัดเจน การเน้นความแตกต่างของความแตกต่างในบรรทัดเพื่อให้คุณเห็นว่าค่าหรือส่วนใดของค่าที่เปลี่ยนแปลงไปอย่างรวดเร็วทำให้ฉันชื่นชอบ

0

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

egrep -v "^$|^[[:space:]]*#" /path/to/file

หรือคุณสามารถทำได้

sed -e '/^#.*/d' -e 's/#.*//g' | cat -s
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.