सीमांकक ट्रिपल पाइप प्रतीक के साथ दो फ़ाइलों को लाइन से मिलाएं "" |||


14

मेरे पास दो भाषाओं में समान संख्या वाली लाइनों के साथ दो समानांतर फाइलें हैं और इन दोनों फाइलों को सीमांत रेखा के साथ मिलाने की योजना है |||। जैसे, दो फाइलें इस प्रकार हैं:

फ़ाइल A:

1Mo 1,1 I love you.
1Mo 1,2 I like you.
Hi 1,3 I am hungry.
Hi 1,4 I am foolish.

फ़ाइल बी:

1Mo 1,1 Ich liebe dich.
1Mo 1,2 Ich mag dich.
Hi 1,3 Ich habe Durst.
Hi 1,4 Ich bin neu.

अपेक्षित आउटपुट इस प्रकार है:

1Mo 1,1 I love you. ||| 1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. ||| 1Mo 1,2 Ich mag dich.
Hi 1,3 I am hungry. ||| Hi 1,3 Ich habe Durst.
Hi 1,4 I am foolish. ||| Hi 1,4 Ich bin neu.

मैंने pasteकमांड की कोशिश की जैसे:

paste -d "|||" fileA fileB

लेकिन लौटा हुआ आउटपुट केवल एक पाइप से युक्त होता है जैसे:

1Mo 1,1 I love you. |1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. |1Mo 1,2 Ich mag dich.

क्या ट्रिप पाइप द्वारा प्रत्येक जोड़ी लाइनों को अलग करने का कोई तरीका है |||?


8
paste -d '|||' fileA - - fileB < /dev/null
स्टीफन चेजलस

5
ऑफटॉपिक, लेकिन आपके अनुवाद सही नहीं हैं;) "इच हैब डर्स्ट" = मैं इस बारे में, "इच बिन नेउ" = मैं नया हूं ... जरूरी नहीं कि आप मूर्ख हैं। ... बस मामले में आप वास्तव में जर्मन सीख रहे हैं ...
dave_alcarin

@ StéphaneChazelas Thx, लेकिन मेरी उत्पादन अभी भी केवल एक ही पाइप युक्त है ...
तेवर

@dave_alcarin डंक सेहर!
तेवर

जवाबों:


20

POSIX पेस्ट के साथ :

:|paste -d ' ||| ' fileA - - - - fileB

pasteसभी इनपुट फ़ाइलों की संगत लाइनों को सम्‍मिलित करेगा। यहां हमारे पास छह फाइलें हैं, fileAमानक में चार डमी फाइलें हैं -, और fileB

परिसीमनकर्ताओं की सूची में एक स्थान, तीन पाइप और उस क्रम में एक स्थान शामिल है जो pasteगोलाकार रूप से उपयोग किया जाएगा ।

छह फ़ाइलों की पहली पंक्ति के लिए, fileAपहली डमी फ़ाइल (जो कुछ भी नहीं है, नो-ऑप: ऑपरेटर के लिए धन्यवाद ) के साथ सम्‍मिलित होगी , निर्माण करें line1-fileA<space>

पहली डमी फ़ाइल को पाइप, प्रोडक्शन द्वारा दूसरे के साथ सम्‍मिलित किया जाएगा line1-fileA |, फिर दूसरी डमी फाइल के साथ तीसरी डमी फाइल, प्रोडक्‍शन line1-fileA ||, आगे की डमी फाइल के साथ तीसरी डमी फाइल, प्रोडक्‍शन line1-fileA |||

और आगे डमी फ़ाइल के साथ fileB, उत्पादन line1-fileA ||| line1-fileB

उन चरणों को सभी लाइनों के लिए दोहराया जाएगा, आपको अपेक्षित परिणाम देंगे।


का उपयोग :|कम-टाइपिंग के लिए होता है, और मुख्य रूप से इंटरेक्टिव शेल में उपयोग होता है। एक स्क्रिप्ट में, आपको उपयोग करना चाहिए:

</dev/null paste -d ' ||| ' fileA - - - - fileB

एक उपसमूह को spawned होने से रोकने के लिए।


1
के लिए +1 :|। चतुर विकल्प</dev/null
कैस

4
... और मानक इनपुट से 4 डमी फ़ाइलों के स्मार्ट उपयोग के लिए +1 - - - -, लेकिन अगली बार जब आप स्पष्टीकरण के लिए कुछ पंक्तियाँ भी लिख सकते हैं :)
11

Thx, लेकिन मुझे अभी भी एक पाइप के साथ आउटपुट मिलता है ...
13:23

@ ३३, क्या आपने सभी डैश और स्पेस कैरेक्टर सहित दिए गए कमांड को ठीक से चलाया? आपका ऑपरेटिंग सिस्टम क्या है?
स्टीफन चेज़लस

:|paste -d '|' fileA - - fileBअंतरिक्ष सीमांकक के बिना अधिक सही संस्करण देता है।
पाल जीडी

7

ठीक है, यह sed, awk या grep का उपयोग नहीं करता है, लेकिन आप इसे बहुत आसानी से bash में कर सकते हैं। आदेश है:

(while IFS= read -r a <&3 && IFS= read -r b <&4; do echo "$a ||| $b"; done) 3<fileA 4<fileB

पेस्ट के साथ समस्या यह है कि सीमांकक एक एकल चरित्र है। आप किसी एकल वर्ण और इसे बदलने के लिए उपयोग sed भी सम्मिलित कर सकते हैं, लेकिन यह एक तरह का त्रुटि-प्रवण होगा यदि वर्ण पहले से ही इनपुट फ़ाइल में दिखाई देता है।


2
यदि लाइन में कोई बैकस्लैश वर्ण है, या डैश के साथ प्रारंभ करने पर आपका समाधान काम नहीं करेगा। आप IFS=प्रत्येक से पहले उपयोग करना चाहते हैं read। आप इसे आसानी से कर सकते हैं paste। देखें मेरा उत्तर भी है, और यह एक को देखने के लिए क्यों का उपयोग कर से बचना चाहिए whileखोल स्क्रिप्ट में पाश।
कोउंगलम

यह मेरी फ़ाइल के लिए काम करता है। कई Thx !!!
तेवर

5

एक awk (GNU) संस्करण

awk '{printf ("%s ||| ", $0); getline < "fileB"; print $0 }' fileA

यदि आप निर्दिष्ट फ़ाइल से अगला सेट करते हैं , तो getlineकमांड के साथ awk, आप $0अगले इनपुट रिकॉर्ड से (कॉलम के लिए सभी चर) सेट कर सकते हैं ।getline < "filename"$0

गेटलाइन <"फ़ाइल" फ़ाइल के अगले रिकॉर्ड से $ 0 सेट करें; NF सेट करें।


जैसा कि आप उम्मीद करते हैं, आपका प्रयास क्यों नहीं हुआ? से man pasteहम पढ़ सकते हैं

-d, --delimiters=LIST
     reuse characters from LIST instead of TABs

लेकिन यह प्रत्येक कॉलम के लिए एक सीमांकक का उपयोग करता है

तो कमांड
paste -d '|*|*' fileA fileB fileA fileBमुझे लाइनों के रूप में देता है

Hi 1,3 I am hungry.|Hi 1,3 Ich habe Durst.*Hi 1,3 I am hungry.|Hi 1,3 Ich...
Hi 1,4 I am foolish.|Hi 1,4 Ich bin neu.*Hi 1,4 I am foolish.|Hi 1,4 Ich...


एक sedसमाधान जो मैं आपके मूल प्रयास के करीब होने पर भी बचने का सुझाव देता हूं, क्योंकि यह आपके मूल उद्देश्य के लिए प्राप्त व्यवहार को पैच करता है:

 paste -d '|' fileA fileB | sed 's/|/|||/g'

बचने के लिए क्योंकि आप प्रत्येक पैटर्न |को नए के साथ प्रतिस्थापित करते हैं |||, लेकिन आपको यह मान लेना होगा कि पाइप प्रतीक ( |) आपके डेटा में मौजूद नहीं है , अन्यथा आपको विशेष मामलों से निपटना होगा और साइड इफेक्ट से बचने के लिए एक अधिक जटिल कोड बनाना होगा।


यहां हिरन [ 1 ] निर्माण के साथ एक प्रकार<<<

 paste -d ' ||| ' fileA - - - - fileB  <<< ''

आप 5 सीमांकक -d ' ||| '(अंतरिक्ष; |; |;; अंतरिक्ष) के साथ और 4 डमी फाइलें ( - - - -) सेट करते हैं जो खाली स्ट्रिंग से डेटा लेगी ''


GNU Awk 4.0.1, पेस्ट (GNU Coreutils) 8.21 और sed (GNU sed) 4.2.2 पर परीक्षण किया गया


Thx, awk कमांड काम करता है!
तेवर

1
आपका स्वागत है। sed(:-)) और अधिक टिप्पणियों से बचने के लिए एक उदाहरण जोड़ने वाले उत्तर को अपडेट किया ।
हस्तूर

4

यदि आप गोलाकार सीमांकक और डमी फ़ाइलों के जादू और नाटक से बचना चाहते हैं, तो आप अपने सीमांकक को केवल एक फ़ाइल में चिपकाने से पहले जोड़ सकते हैं:

paste <(sed 's/$/ |||/' filea) fileb

देता है

1Mo 1,1 I love you. ||| 1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. ||| 1Mo 1,2 Ich mag dich.
Hi 1,3 I am hungry. ||| Hi 1,3 Ich habe Durst.
Hi 1,4 I am foolish. |||    Hi 1,4 Ich bin neu.

मुझे यह सादगी पसंद है। मेरा मानना ​​है कि आप का अर्थ "प्रीपेन्ड" है, न कि "अपेंडेंड"। इस के जागृत संस्करण के लिए चेकआउट हस्तूर का जागृत उत्तर।
वाइल्डकार्ड

आपको प्रक्रिया प्रतिस्थापन को एक पाइप में बदलना चाहिए, इसलिए आपके पास समर्थन करने वाले गोले की संख्या की सीमा नहीं होगी।
congonglm

@Wildcard हाँ, प्रीपेन्ड करें, लेकिन मैं इसे फ़िलिया में संलग्न करने के लिए फिर से लिखूंगा। मुझे लगता है कि awk इसके लिए थोड़ा ओवरकिल है।
सांप

@cuonglm सच है, लेकिन मैं स्पष्टता के लिए पाइप से बचना चाहता था। मैं एक पाइप यह डमी फ़ाइलें तरह देखने के लिए शुरू होगा महसूस किया, लेकिन आप सही हैं
snth

0

आप इसे अजगर में भी इस तरह से कर सकते हैं।

lines1 = [ line.rstrip() for line in open("file1") ]
lines2 = [ line.rstrip() for line in open("file2") ]
for i in xrange((len(lines1))): print lines1[i] + " ||| " + lines2[i]
... 
1Mo 1,1 I love you. ||| 1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. ||| 1Mo 1,2 Ich mag dich.
Hi 1,3 I am hungry. ||| Hi 1,3 Ich habe Durst.
Hi 1,4 I am foolish. ||| Hi 1,4 Ich bin neu.
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.