पाठ प्रसंस्करण - हर दो पंक्तियों में अल्पविराम से जुड़ें


35

मेरे पास एक फ़ाइल में 1000 से अधिक लाइनें हैं। फ़ाइल निम्नानुसार शुरू होती है (पंक्ति संख्या जोड़ी गई):

Station Name
Station Code
A N DEV NAGAR
ACND
ABHAIPUR
AHA
ABOHAR
ABS
ABU ROAD
ABR

मुझे इसे एक फाइल में बदलने की जरूरत है, हर दो लाइनों में शामिल होने के लिए अल्पविराम से अलग प्रविष्टियों के साथ। अंतिम डेटा जैसा दिखना चाहिए

Station Name,Station Code
A N DEV NAGAR,ACND
ABHAIPUR,AHA
ABOHAR,ABS
ABU ROAD,ABR
...

मैं जो कोशिश कर रहा था - वह एक शेल स्क्रिप्ट लिखने की कोशिश कर रहा था और फिर echoउनके बीच में अल्पविराम था। लेकिन मुझे लगता है कि एक सरल-प्रभावी एक-लाइनर यहां काम करेगा sed/ हो सकता है awk

कोई विचार?


@ l0b0 आपने ओपी की टिप्पणी को संपादित किया कि लाइन नंबर "केवल स्पष्टीकरण के लिए वहां हैं" ...
जसोवरीयन

@jasonwryan क्षमा करें, मुझे लगा कि स्पष्टीकरण के लिए लाइनें थीं। लाइन में पार्स त्रुटि 0.
l0b0

जवाबों:


39

बस का उपयोग करें cat(यदि आप बिल्लियों की तरह; ;-)) और paste:

cat file.in | paste -d, - - > file.out

स्पष्टीकरण: pasteएक साथ कई फाइलों और पेस्टों को एक साथ पढ़ता है और इसी पंक्तियों (लाइन 1 से पहली फाइल के साथ लाइन 1 से दूसरे नंबर) आदि को पढ़ता है:

paste file1 file2 ...

एक फ़ाइल नाम के बजाय, हम -(डैश) का उपयोग कर सकते हैं । pasteफ़ाइल 1 से पहली पंक्ति लेता है (जो स्टडिन है)। फिर, यह फ़ाइल 2 से पहली पंक्ति पढ़ना चाहता है (जो कि स्टडिन भी है)। हालांकि, चूंकि स्टडिन की पहली पंक्ति पहले से ही पढ़ी गई थी और संसाधित की गई थी, अब इनपुट स्ट्रीम पर जो इंतजार होता है, वह स्टड की दूसरी पंक्ति है, जो pasteपहले वाले को खुशी से झलकती है। -dविकल्प सीमांकक एक टैब एक अल्पविराम के बजाय होने के लिए सेट करता है।

वैकल्पिक रूप से, करते हैं

cat file.in | sed "N;s/\n/,/" > file.out

PS हाँ, कोई भी ऊपर को सरल बना सकता है

< file.in sed "N;s/\n/,/" > file.out

या

< file.in paste -d, - - > file.out

जिसका उपयोग न करने का फायदा है cat

हालाँकि, मैंने इस मुहावरे का उपयोग उद्देश्य के लिए , स्पष्टता कारणों से नहीं किया है - यह कम क्रिया है और मुझे पसंद है cat(CATS NICE)। तो कृपया संपादित न करें।

वैकल्पिक रूप से, यदि आप बिल्लियों को पेस्ट पसंद करते हैं (पेस्ट क्षैतिज रूप से फ़ाइलों को संक्षिप्त करने के लिए कमांड है, जबकि बिल्ली उन्हें लंबवत रूप से व्यवस्थित करती है), तो आप उपयोग कर सकते हैं:

paste file.in | paste -d, - -

बस फिर से उल्लेख करना है। लाइन नंबर फ़ाइल का हिस्सा नहीं हैं :)
mtk

paste आदेश पूरी तरह से काम करता है, आप इसके बारे में थोड़ा और अधिक स्पष्टीकरण दे कृपया कर सकते हैं। हाइफ़न ???
mtk

2
हाइफ़न का अर्थ है "स्टडिन से पढ़ा गया"। यदि एक ही इनपुट स्रोत दोहराया जाता है, तो पेस्ट आउटपुट की प्रति पंक्ति से कई बार इसे पढ़ना जानता है।
dubiousjim

@ एससीएच: कूल एडिट, मैं इसे नहीं छूऊंगा :-)
जनवरी

1
अपने catतर्क के संबंध में । करता है sed "N;s/\n/,/" file.in > file.outकाम नहीं?
बर्नहार्ड

8

यदि कोई व्यक्ति यहां उतर रहा है तो सभी लाइनों को एक सीएसवी वन लाइनर में संयोजित करने की कोशिश करें

cat file | tr '\n' ','

3
sed 'N;s/\n/,/' file

Sed का उपयोग करते हुए, हर 2 लाइनों में शामिल (N) करें, और "," के साथ newline (\ n) को बदलें।


3
paste -sd ',\n' file.in > file.out

यह भी ध्यान दें कि क्योंकि हम केवल एक वर्ण को दूसरे के साथ बदल रहे हैं (अल्पविराम के साथ हर दूसरी पंक्ति), हम यात्रा में इनपुट पर काम कर सकते हैं:

paste -sd ',\n' file.in 1<> file.in

(लेकिन सावधान रहें कि यह उन गैर-यूनिक्स प्रणालियों पर काम नहीं कर सकता है जिनके पास CRLF टर्मिनेटर हैं (जैसे Microsoft वाले) जो कुछ अनुकरण किए गए POSIX pasteगैर-यूनिक्स तरीके से व्यवहार कर सकते हैं)


यहाँ क्या 1कर रहा है 1<>? क्या वह टाइपो है?
α atsнιη

@ αғsнιη, देखना यह
इरुवर

@iruvar शुक्रिया
αғsнι

2

यहां शुद्ध बैश का उपयोग करके एक-लाइनर (हालांकि संभावित लाखों-कमांड-रन-एर) है:

(IFS=; while read -r name; do read -r code; printf '%s\n" "$name,$code"; done < file.in) > file.out

मैं एक उपखंड (परपेंटिस) का उपयोग करता हूं, ताकि मुझे स्टोर और पुनर्स्थापित न करना पड़े IFS। यदि स्रोत स्रोत से हटा दिया जाता है तो उपयोगकर्ताओं को पर्यावरण को गड़बड़ाने के लिए कौन से अन्यथा करना चाहिए। विकल्प केवल करने के लिए है कि नए भारतीय विदेश सेवा पारित करने के लिए किया जाएगा readके रूप में IFS= read -r name, IFS= read -r code

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


सामान्य तौर पर पर्यावरणीय परिवर्तनों को स्थानीय बनाने के लिए उपधाराओं का उपयोग करने के लिए। लेकिन इस मामले में इसकी आवश्यकता नहीं है: आप इसके बजाय कर सकते हैं while IFS='\n' read -r name; do IFS='\n' read -r code ... done < file.in, जो एक मुहावरा है जिसे मैं अक्सर शेल स्क्रिप्ट में देखता हूं। -rकरने के लिए ध्वज readका अर्थ है "वर्ण '\' दो अक्षर, बल्कि एक नई पंक्ति के रूप में की तुलना में stdin धारा में चरित्र 'एन' के बाद की व्याख्या।" तर्क के रूप में, यह उपकथा बनाने के लिए अधिक सौंदर्य हो सकता है जैसा कि आप दोहराते हैं IFS='\n'
dubiousjim

@dubiousjim: -rतकनीकी रूप से समाधान में सुधार। महान! मैं एक परिवर्तित IFSदो बार पारित करने के विचार का प्रशंसक नहीं हूं । अगर मैंने एक पढ़ा, सुपर अच्छा, लेकिन दो बार नहीं। बेशक यह राय का विषय है । एक उपखंड का उपयोग करना सामान्य बैश ज्ञान पर थोड़ा सा होगा जो मैं कहूंगा, इसलिए बहुत सारे लोगों को इसके उद्देश्य को समझने में परेशानी होगी। यह एक बुरी बात है।
नष्ट कर दिया

2

उत्तरों के पूर्ण सेट के लिए, एक संभावित awkसमाधान हो सकता है:

awk 'NR%2==1 {printf $0","} NR%2==0 { print $0}' *file*

@downvoter: मेरे जवाब में गलती करने के लिए क्या गलत है? इसमें कैसे सुधार किया जा सकता है?
बर्नहार्ड

शायद इसलिए कि आलसी printf? उस दुर्लभ स्थिति में विफल हो जाएगा जब किसी स्टेशन के नाम में एक प्रारूप निर्दिष्ट होता है। ( एक उदाहरण के लिए pastebin.com/wgxFttrJ देखें ।) लेकिन यह सिर्फ एक अनुमान है, डाउनवोट मुझसे नहीं है।
मैनटवर्क

1

एक awkमुहावरे की पुरानी पुरानी छाती

awk '{ORS=NR%2?",":"\n";print}' file
Station Name,Station Code
A N DEV NAGAR,ACND
ABHAIPUR,AHA
ABOHAR,ABS
ABU ROAD,ABR

awk '{ORS=NR%2?",":"\n"};1'कम है और अधिक मुहावरे
cuonglm

@cuonglm, मुझे संदेह है। इस उदाहरण में यह अभी भी एक-लाइनर है printऔर इरादे स्पष्ट हैं। 1सिर्फ awkअपने जैसे पुराने हाथों के लिए स्पष्ट है, लेकिन मैं पसंद करता हूंprint
iruvar

यह पहला सरल समाधान था जो मैंने पाया कि आसानी से 2 से अधिक लाइनों के लिए कॉन्फ़िगर किया गया था। मैंने sedखोज करने से पहले कुछ समय के लिए संघर्ष किया , लेकिन awkहर 4 लाइनों के संयोजन को आसान बना दिया। मुझे एक यात्रा के लिए बचा लिया $EDITOR!
opello


0

उदाहरण के लिए:

seq 0 70 | xargs -L 2 | sed 's/ /,/g'

आउटपुट: (नोट: xargs -L number_of_columnsप्रत्येक दो पंक्तियों में न केवल कॉलम की किसी भी संख्या के साथ अच्छी तरह से काम करता है)

0,1
2,3
4,5
6,7
8,9
10,11
12,13
14,15
16,17
18,19
20,21
22,23
24,25
26,27
28,29
30,31
32,33
34,35
36,37
38,39
40,41
42,43
44,45
46,47
48,49
50,51
52,53
54,55
56,57
58,59
60,61
62,63
64,65
66,67
68,69
70

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