बाश में स्ट्रिंग अंतर


110

मैं अपनी स्क्रिप्ट में दो तारों के बीच के अंतर को निर्धारित करने का एक तरीका खोजने की कोशिश कर रहा हूं। मैं आसानी से अंतर या कम के साथ ऐसा कर सकता था, लेकिन मैं फ़ाइलों के साथ काम नहीं कर रहा हूं और मैं उन्हें फाइलों में आउटपुट नहीं करना चाहता हूं, तुलना करें और वापस पढ़ें।

मुझे लगता है कि कॉम, विस्‍तारित, cmp सभी दो फ़ाइलों या एक फ़ाइल और मानक इनपुट को पारित करने की अनुमति देते हैं - मुझे लगता है कि अगर मैं दो फ़ाइलों का उत्पादन नहीं करना चाहता तो अच्छा है ... लेकिन यह अभी भी थोड़े बेकार है।

सोच के आसपास खुदाई कर रहा हूं मैं grep या नियमित अभिव्यक्ति का उपयोग कर सकता हूं - लेकिन मुझे लगता है कि नहीं।


1
यह आप वास्तव में क्या करना चाहते हैं?

आप तुलना करने के लिए IFS परिवर्तनों के साथ प्रतिस्थापन हेरफेर और बिलिन टेस्ट ऑपरेशन का उपयोग कर सकते हैं, लेकिन आपको यह जानना होगा कि क्या आप चरित्र द्वारा वर्ण की तुलना करना चाहते हैं, शब्द से शब्द, लाइन से लाइन, सफेद स्थान को अनदेखा करें ...
Technosaurus

जवाबों:


198

का उपयोग करना diffया comजो आप चाहते हैं:

diff  <(echo "$string1" ) <(echo "$string2")

ग्रेग बैश FAQ: प्रक्रिया प्रतिस्थापन

या एक नामित पाइप के साथ

mkfifo ./p
diff - p <<< "$string1" & echo "$string2" > p

ग्रेग बैश एफएक्यू: नामांकित पाइप के साथ काम करना

नामांकित पाइप को एक फीफो के रूप में भी जाना जाता है।

-अपने आप ही मानक इनपुट के लिए है।

<<< एक "यहाँ स्ट्रिंग" है।

&की तरह है, ;लेकिन इसे पृष्ठभूमि में रखता है


5
सही उत्तर के लिए +1। प्रतीकों के महान विवरण के लिए +1। इसके अतिरिक्त, ग्रेग के बैश अकसर किये गए सवाल: mywiki.wooledge.org पर जा चुके हैं । उपरोक्त पेजों के लिंक अब mywiki.wooledge.org/ProcessSubstitution और mywiki.wooledge.org/BashFA3/085 पर उपलब्ध हैं
timemachine3030

धन्यवाद! और यह भी, यह डायनामिक फ़ाइल डिस्क्रिप्टरFUNC(){ echo "$@"; "$@"; }; FUNC diff <(echo a) <(echo b);
कुंभ पावर

मैं दो shasums कम्पेयर करने के लिए देख रहा था। निश्चित नहीं है कि ऐसा करने के लिए अधिक सुरुचिपूर्ण तरीका है, लेकिन यह काम करता है।
फ़ूमा

यह काम करने लगता है अगर $ string1 और $ string2 में कई लाइनें हैं, और जो लाइनों को जोड़ा या घटाया गया है, उसे आउटपुट में अंतर करता है। क्या होगा यदि स्ट्रिंग एक एकल रेखा और रेखा है और दोनों तारों के बीच कुछ अंतर है?
अल्फा_ 989

@ Alpha_989, यहां आपका जवाब है: $ diff <(echo "Here are the letters in String One.") <(echo "Here are the characters in String Two.") \n 1c1 \n < Here are the letters in String One. \n --- \n > Here are the characters in String Two. \nपाइप का उपयोग करना समान है, सिवाय इसके कि यह एक प्रक्रिया संख्या दिखाता है, 1c1अगले के बाद से शुरू होता है $, और इंतजार करता है जब तक आप <kbd> Enter <kbd> (या आप अन्य कमांड कर सकते हैं ...)
bballdave025

19

इस प्रश्न की याद दिलाता है: आप बैश में दो पाइपलाइनों को कैसे अलग कर सकते हैं?

यदि आप एक बैश सत्र में हैं, तो आप निम्न कार्य कर सकते हैं:

diff <cmd1 <cmd2
diff <(foo | bar) <(baz | quux)

<अनाम पाइप बनाने के साथ - बैश द्वारा प्रबंधित - इसलिए वे अस्थायी फ़ाइलों के विपरीत, स्वचालित रूप से बनाए और नष्ट किए जाते हैं।

इसलिए यदि आप अपने दो अलग-अलग स्ट्रिंग को एक कमांड (grep, awk, sed, ...) के हिस्से के रूप में अलग करने का प्रबंधन करते हैं, तो आप कर सकते हैं - उदाहरण के लिए - कुछ ऐसा:

diff < grep string1 myFile < grep string2 myFile

(यदि आपको लगता है कि आपके पास आपकी फ़ाइल लाइनें हैं जैसे string1=very_complicated_valueऔर string2=another_long_and_complicated_value': आपकी फ़ाइल के आंतरिक प्रारूप को जाने बिना, मैं एक सटीक प्रोग्राम की सिफारिश नहीं कर सकता हूं)


13

मैं पसंद cmpऔर प्रक्रिया को प्रतिबंधित करने की सुविधा:

$ cmp -bl <(echo -n abcda) <(echo -n aqcde)
  2 142 b    161 q
  5 141 a    145 e

स्थिति 2 पर कहते हैं, पहली के लिए ab होता है, लेकिन दूसरे के लिए aq। स्थिति 5 पर, एक और अंतर हो रहा है। बस उन तारों को चर द्वारा प्रतिस्थापित करें, और आप कर रहे हैं।


यह तभी काम करता है जब तार समान लंबाई के हों!
strpeter

11

कहते हैं कि आपके पास तीन तार हैं

a="this is a line"
b="this is"
c="a line"

एक से उपसर्ग ख को हटाने के लिए

echo ${a#"$b"}  # a line

प्रत्यय c को हटाने के लिए a

echo ${a%"$c"}  # this is

2
मुझे लगता है कि यह इसे करने का तरीका है। यह अच्छी तरह से काम किया। हालांकि वाक्य रचना थोड़ा मुश्किल है।
मिकेल रोज

@ मिकेलरोस सहमत। : आसान (मेरे लिए वैसे भी) को पढ़ने के लिए उपयोग करने के लिए sed होगा echo "$a" | sed "s!^$b!!g" (!। मैं बदली मानक एसईडी विभाजक / मामले में के लिए चर के साथ रास्ते हैं इसके अलावा निपटा जा रहा है आप एक यहाँ स्ट्रिंग गूंज के बजाय इस्तेमाल कर सकते हैं,: sed ... <<< $a।)
ACK_stoverflow

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.