टिप्पणियों की अनदेखी करने वाली फ़ाइलों को कैसे अलग करें (# के साथ शुरू होने वाली लाइनें)?


55

मेरे पास दो कॉन्फ़िगरेशन फाइलें हैं, पैकेज मैनेजर से मूल और स्वयं द्वारा संशोधित एक अनुकूलित। मैंने व्यवहार का वर्णन करने के लिए कुछ टिप्पणियां जोड़ी हैं।

मैं diffकॉन्फ़िगरेशन फ़ाइलों पर कैसे चल सकता हूं , टिप्पणियों को लंघन? एक टिप्पणी लाइन द्वारा परिभाषित किया गया है:

  • वैकल्पिक प्रमुख व्हाट्सएप (टैब और स्पेस)
  • हैश साइन ( #)
  • कुछ और चरित्र

पहली आवश्यकता को छोड़ना सबसे सरल (सबसे सरल) नियमित अभिव्यक्ति होगी #.*। मैंने GNU 3.0 के विकल्प की --ignore-matching-lines=RE( -I RE) विकल्प की कोशिश की , लेकिन मैं इसे आरई के साथ काम नहीं कर पाया। मैंने भी कोशिश की .*#.*और .*\#.*बिना किस्मत के। शाब्दिक Port 631रूप से लाइन डालना ( ) REकुछ भी मेल नहीं खाता है, न ही यह स्लैश के बीच आरई लगाने में मदद करता है।

जैसा कि रेगेक्स के उपकरण के स्वाद में "कमी" की कमी है? , मैंने कोशिश की grep -G:

grep -G '#.*' file

यह टिप्पणियों से मेल खाता है, लेकिन यह काम नहीं करता है diff -I '#.*' file1 file2

तो, इस विकल्प का उपयोग कैसे किया जाना चाहिए? मैं diffकुछ लाइनें (मेरे मामले में, टिप्पणी) को कैसे छोड़ सकता हूं ? कृपया grepफ़ाइल को आईएनजी और अस्थायी फ़ाइलों की तुलना करने का सुझाव न दें ।


12
इस -Iविकल्प के कारण ब्लॉक को केवल तभी अनदेखा किया जा सकता है जब उसकी सभी पंक्तियाँ regexp से मेल खाती हों। इसलिए आप एक टिप्पणी को केवल उस तरीके से बदल सकते हैं, लेकिन टिप्पणी में परिवर्तन नहीं जो कि एक गैर-टिप्पणी परिवर्तन के निकट हैं।
गिल्स एसओ- बुराई को रोकना '

@ गिल्स: थैंक्स, अब मुझे वह मिल गया diff -Iहै, जैसा मैंने अपेक्षित था, वैसा व्यवहार नहीं किया। मैंने अपने उत्तर को एक उदाहरण के साथ अद्यतन किया जिसने मेरे लिए इस व्यवहार को स्पष्ट किया।
लेकेनस्टीन

जवाबों:


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विकल्प का सही तरीके से उपयोग करने के तरीके के बारे में अब तक कोई जवाब नहीं है, इसलिए मैं एक विकल्प प्रदान करूंगा जो बैश के गोले में काम करता है:

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- आरक्षित वर्ण (जैसे कोष्ठक) से बचने के लिए एकल उद्धरण का उपयोग करें।

हम diffutilsमैनुअल में पढ़ सकते हैं :

हालांकि, -Iकेवल उन पंक्तियों के सम्मिलन या विलोपन को अनदेखा करता है जिनमें नियमित अभिव्यक्ति होती है यदि हंक में हर परिवर्तित रेखा (हर प्रविष्टि और प्रत्येक विलोपन) नियमित अभिव्यक्ति से मेल खाती है।

दूसरे शब्दों में, प्रत्येक गैर-अज्ञानी परिवर्तन के लिए, diffअपने आस-पास के परिवर्तनों का पूरा सेट प्रिंट करता है, जिसमें आग्नेय भी शामिल हैं। आप लाइनों के लिए एक से अधिक नियमित अभिव्यक्ति को एक से अधिक -Iविकल्पों का उपयोग करके अनदेखा कर सकते हैं । diffप्रत्येक नियमित अभिव्यक्ति के खिलाफ प्रत्येक पंक्ति से मेल खाने की कोशिश करता है, जो पिछले दिए गए से शुरू होता है।

यह व्यवहार यहाँ कवच द्वारा भी अच्छी तरह से समझाया गया है

संबंधित: मैं एक ऐसी टिप्पणी कैसे कर सकता हूं जो सभी टिप्पणियों को अनदेखा करती है?


2

वेब के चारों ओर खोज करने के बाद, लेकेनस्टीन का वैकल्पिक तरीका मुझे मिला बेहतर है।

लेकिन मैं पैच के रूप में अलग आउटपुट का उपयोग करना चाहता हूं ... और एक समस्या है क्योंकि लाइन संख्या को "grep -v" के कारण नोट किया जाता है।

इसलिए मुझे इस कमांड लाइन में सुधार करना है:

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

यह सही नहीं है, लेकिन पैच फ़ाइल में लाइन नंबर रखे गए हैं।

हालाँकि, यदि टिप्पणी लाइन के बजाय एक नई लाइन जोड़ी जाती है ... टिप्पणी एक हंक विफलता का उत्पादन करेगी जब पैचिंग के रूप में हम बलो को देख सकते हैं।

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 प्रक्रिया प्रतिस्थापन द्वारा निर्मित फ़ाइल हैं। "+ नई लाइन" और "-उत्तर पाठ" के बीच की रेखा टिप्पणियों को बदलने के लिए हमारी 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

समाधान न-यू के बिना एकीकृत रूप प्रारूप का उपयोग करना है

$ 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 -U0 one twoसंदर्भ को अक्षम करने के लिए उपयोग कर सकते हैं । पैचिंग के लिए, उपकरणों का एक समूह है जो कि kdiff3 जैसे बेहतर अनुकूल हो सकते हैं।
लेकेन्स्टाइन

-U0संदर्भ को अक्षम करने के विकल्प के लिए धन्यवाद । नोट: kdiff3 एक ग्राफिकल टूल है। मुझे git मर्ज विशेषताओं को प्रबंधित करने के लिए स्वचालित टूल की आवश्यकता है।
syjust

vimdiffतीन-तरफा मर्ज का समर्थन करता है, देखने लायक हो सकता है।
लेकेन्स्टाइन

अधिक सटीक होने के लिए, मुझे एक sql स्क्रिप्ट में एक्सल के साथ git मर्ज प्रक्रिया को स्वचालित करने के लिए एक स्क्रिप्ट टूल की आवश्यकता है। kdiff3 और vimdiff अंतःक्रियात्मक उपकरण हैं, मेरे मामले में प्रयोग करने योग्य नहीं हैं।
संयोग

1

मैं आमतौर पर इस अव्यवस्था को अनदेखा करता हूं:

  • गैर-टिप्पणी वाले संस्करणों का उपयोग करना grep -v "^#" | cat -sऔर उन्हें अलग करना या बनाना ...
  • vim -dफ़ाइलों को देखने के लिए उपयोग करना । वाक्य रचना हाइलाइटिंग टिप्पणी बनाम गैर-टिप्पणी मतभेदों को स्पष्ट रूप से ध्यान में रखती है। इन-लाइन अंतर का अलग-अलग हाइलाइटिंग ताकि आप देख सकें कि एक नज़र में मूल्यों या मूल्यों को क्या बदल दिया गया है, यह मेरा पसंदीदा बनाता है।

0

यहाँ मैं सभी टिप्पणी की गई पंक्तियों को हटाने के लिए उपयोग करता हूँ -जिससे एक टैब या स्थान के साथ शुरू होने वाले और रिक्त स्थान:

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

या आप कर सकते हैं

sed -e '/^#.*/d' -e 's/#.*//g' | cat -s
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.