2011-12-15 21 views
59

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

उदाहरण। तीन लाइनों के साथ एक पाठ फ़ाइल, foo.txt पर विचार करें,:

foo 
bar 
baz 

वांछित आउटपुट है:

foo,bar,baz 

आदेश अब मैं उपयोग कर रहा हूँ:

tr '\n' ',' <foo.txt |sed 's/,$//g' 

आदर्श रूप में यह कुछ होगा इस तरह:

cat foo.txt |join , 

क्या है:

  1. सबसे पोर्टेबल, संक्षिप्त, पठनीय तरीका।
  2. गैर-मानक यूनिक्स उपकरण का उपयोग करके सबसे संक्षिप्त तरीका।

बेशक मैं कुछ लिख सकता हूं, या सिर्फ उपनाम का उपयोग कर सकता हूं। लेकिन मुझे विकल्पों को जानने में दिलचस्पी है।

paste -s -d"," 

यह खाली लाइनों आप का उल्लेख के साथ सौदा नहीं होगा:

+0

(http://stackoverflow.com/questions/2764051/joining-multiple-lines-into-one-with-bash) –

उत्तर

93

शायद एक छोटे से आश्चर्यजनक रूप से, paste यह करने के लिए एक अच्छा तरीका है। उसके लिए, पाइप grep के माध्यम से अपने पाठ, पहला:

grep -v '^$' | paste -s -d"," - 
+0

@codaddict न ही मैं [बैश के साथ एक में कई पंक्तियों में शामिल होने से] के संभावित डुप्लिकेट, लेकिन मैं यह स्वीकार करना होगा कि मुझे यह सहज नहीं लगता है - मुझे हमेशा इसके लिए मैन पेजों की जांच करने की आवश्यकता है। मैं निश्चित रूप से उत्सुक हूं कि दूसरों को क्या सुझाव है। –

+0

हे, धन्यवाद, मुझे यह आदेश भी नहीं पता था! – fge

+0

अन्य तरीके भी हैं, लेकिन कोई भी अच्छा नहीं है (और मजेदार लोग थोड़ी परेशान हैं)। – Sorpigal

4

बस मस्ती के लिए, यहाँ एक सब builtins समाधान है

IFS=$'\n' read -r -d '' -a data < foo.txt ; (IFS=, ; echo "${data[*]}" ;) 

आप printf बजाय echo उपयोग कर सकते हैं अनुगामी न्यू लाइन एक समस्या है।

यह IFS की स्थापना करके काम करता है, सीमांकक कि read पर, बस न्यू लाइन और नहीं अन्य खाली स्थान के लिए, तो read कह पढ़ने जब तक यह एक nul तक पहुँच जाता है बंद नहीं करने के लिए करने के लिए, यह आम तौर पर न्यू लाइन का उपयोग करता है के बजाय विभाजित होगा, और जोड़ने के लिए प्रत्येक आइटम सरणी में पढ़ा जाता है (-a) डेटा। फिर, एक subshell में इंटरैक्टिव खोल के IFS पीटना इतनी के रूप में नहीं करने के लिए, हम , को IFS सेट और * के साथ सरणी, जो IFS

+0

दिलचस्प है, हालांकि पोर्टेबिलिटी उत्कृष्ट नहीं है, क्योंकि शुद्ध 'sh' shell 'read' कमांड में कोई' -d' विकल्प नहीं है। – mykhal

+0

@mykhal: सच है। हालांकि, कई प्रणालियों पर 'बाश' पाया जा सकता है, इसलिए इसमें कुछ उपयोगिता है। यदि आप चाहते हैं कि पोर्टेबिलिटी सरणी शायद बाहर भी हों, अन्यथा आप '-d' की कमी के आसपास काम करने के लिए बस 'लूप' का उपयोग कर सकते हैं। एक उचित, पोर्टेबल ऑल-बिल्टिन संस्करण के लिए आप कुछ चाहते हैं जैसे 'c =; जबकि आईएफएस = read -r डी; अगर करो! [-z "$ डी"]; फिर printf "$ c $ d"; फाई सी =,; Sorpigal

12

यह sed एक- में पहले वर्ण के साथ सरणी में प्रत्येक आइटम delimits का विस्तार लाइन काम करना चाहिए -

sed -e :a -e 'N;s/\n/,/;ba' file

टेस्ट:

[jaypal:~/Temp] cat file 
foo 
bar 
baz 

[jaypal:~/Temp] sed -e :a -e 'N;s/\n/,/;ba' file 
foo,bar,baz 

खाली लाइनों को संभालने के लिए, आप खाली लाइनों को हटा सकते हैं और इसे उपरोक्त एक-लाइनर पर पाइप कर सकते हैं।

sed -e '/^$/d' file | sed -e :a -e 'N;s/\n/,/;ba' 
+6

महान जवाब! अब शोध करने के लिए उन नए sed आदेशों का मतलब क्या है .. – fuzzyTew

+0

एक स्पष्टीकरण अच्छा होगा! –

+0

दो-अभिव्यक्ति को एक में जोड़ने के लिए और अधिक स्पष्ट है, 'sed -e': a; एन; s/\ N /, /; ba''। लेकिन यह अभी भी एक ओ (एन²) विधि है, क्योंकि जब भी कोई नई लाइन जोड़ा जाता है तो sed कुछ प्रतिस्थापन करेगा। 'sed -e': ए; एन; ! $ बा; एस/\ n /,/g'' रैखिक है, सभी लाइनों को sed के पैटर्न स्पेस में जोड़ दिए जाने के बाद केवल एक बार प्रतिस्थापित किया जाता है। '$! ba' का अर्थ है" अगर यह आखिरी पंक्ति है ($) नहीं (!) कूदें (बी) लेबल (ए) लेबल: ए (ए), लूप तोड़ें " – zhazha

0

मैं एक फ़ाइल से मुद्रण क्षेत्रों में से एक अल्पविराम से अलग किए कुछ इसी तरह पूरा करने के लिए की जरूरत है, और xargs और ruby लिए पाइपिंग STDOUT से खुश था, जैसे इतना:

cat data.txt | cut -f 16 -d ' ' | grep -o "\d\+" | xargs ruby -e "puts ARGV.join(', ')" 
5

पर्ल:

cat data.txt | perl -pe 'if(!eof){chomp;$_.=","}' 

या अभी तक छोटे और तेज, आश्चर्यजनक रूप से:

cat data.txt | perl -pe 'if(!eof){s/\n/,/}' 

या, अगर आप चाहते हैं:

cat data.txt | perl -pe 's/\n/,/ unless eof' 
+1

इस बारे में अच्छी बात यह है कि आप किसी भी स्ट्रिंग का उपयोग कर सकते हैं बस एक साधारण कॉमा। स्वीकृत उत्तर कम बहुमुखी है। मुझे विशेष रूप से अंतिम पुनरावृत्ति पसंद है, हालांकि मैंने इसे लिखा होगा: 'perl -pe'/\ n /,/जब तक eof 'data.txt' (नकली बिल्ली की आवश्यकता नहीं है)। –

0

(भी रिक्त लाइनों अनदेखी) ex का उपयोग कर, उपयोग में जगह जगह के साथ लाइनों में शामिल होने का सरल तरीका:

ex +%j -cwq foo.txt 

आप चाहते हैं मानक आउटपुट में परिणाम प्रिंट, कोशिश:

ex +%j +%p -scq! foo.txt 

रिक्तियों के बिना लाइनों में शामिल होने के लिए,का उपयोग +%j के बजाय।

अलग सीमांकक का उपयोग करने के लिए, उसे कुछ अतिरिक्त मुश्किल है:

ex +"g/^$/d" +"%s/\n/_/e" +%p -scq! foo.txt 

जहां g/^$/d (या v/\S/d) रिक्त लाइनों दूर करता है और s/\n/_/ प्रतिस्थापन जो मूल रूप से sed का उपयोग कर के रूप में ही काम करता है, लेकिन सभी लाइनों के लिए (%)। जब पार्सिंग की जाती है, तो बफर प्रिंट करें (%p)। और अंत में -cq! vi q! कमांड निष्पादित करता है, जो मूल रूप से सहेजे बिना छोड़ देता है (-s आउटपुट को चुप करना है)।

कृपया ध्यान दें कि exvi -e के बराबर है।

यह विधि काफी पोर्टेबल है क्योंकि अधिकांश लिनक्स/यूनिक्स को ex/vi डिफ़ॉल्ट रूप से भेज दिया जाता है। और यह sed का उपयोग करने से अधिक संगत है जहां जगह-जगह पैरामीटर (-i) मानक एक्सटेंशन और उपयोगिता नहीं है, यह स्वयं स्ट्रीम उन्मुख है, इसलिए यह इतना पोर्टेबल नहीं है।

7

xargs का उपयोग कैसे करें?

अपने मामले के लिए

$ cat foo.txt | sed 's/$/, /' | xargs 

xargs आदेश के इनपुट की सीमा की लंबाई के बारे में सावधान रहें। (इसका मतलब है कि बहुत लंबी इनपुट फ़ाइल को इस से नियंत्रित नहीं किया जा सकता है।)

+0

मुझे xargs पर '-L' ध्वज मिला '-L 50' प्रति पंक्ति 50 आइटम होगा। – jmunsch

0

मेरे पास एक लॉग फ़ाइल थी जहां कुछ डेटा एकाधिक लाइनों में टूट गया था। जब यह हुआ, पहली पंक्ति का अंतिम चरित्र सेमी-कोलन (;) था। मैं निम्न कमांड का उपयोग करके इन पंक्तियों में शामिल हो गए:

for LINE in 'cat $FILE | tr -s " " "|"' 
do 
    if [ $(echo $LINE | egrep ";$") ] 
    then 
     echo "$LINE\c" | tr -s "|" " " >> $MYFILE 
    else 
     echo "$LINE" | tr -s "|" " " >> $MYFILE 
    fi 
done 

परिणाम एक फ़ाइल जहां लाइनों कि लॉग फ़ाइल में विभाजित किया गया मेरा नया फ़ाइल में एक पंक्ति थे।

-1

मेरा जवाब है:

awk '{printf "%s", ","$0}' foo.txt 

printf पर्याप्त है। फील्ड विभाजक बदलने के लिए हमें -F"\n" की आवश्यकता नहीं है।

+1

यह आउटपुट की शुरुआत में एक नकली कॉमा जोड़ता है। परीक्षण के लिए -1। –

संबंधित मुद्दे