एक ही हेडर के साथ कई फाइलों को समेटना


26

मेरे पास एक ही हैडर और उसके नीचे अलग-अलग वैक्टर वाली कई फाइलें हैं। मुझे उन सभी को संक्षिप्त करने की आवश्यकता है, लेकिन मैं चाहता हूं कि केवल पहली फ़ाइल के शीर्षलेख को संक्षिप्त किया जाए और मैं नहीं चाहता कि अन्य शीर्षकों को संक्षिप्त किया जाए क्योंकि वे सभी समान हैं।

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

<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B 
C

file2.txt

<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
D
E 
F

मुझे आउटपुट चाहिए

<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B
C
D
E 
F

मैं आर में एक स्क्रिप्ट लिख सकता हूं लेकिन मुझे शेल में इसकी आवश्यकता है?

जवाबों:


17

यदि आप जानते हैं कि इसे आर में कैसे करना है, तो हर तरह से इसे आर। में शास्त्रीय यूनिक्स उपकरणों के साथ करें, यह सबसे स्वाभाविक रूप से जाग में किया जाता है।

awk '
    FNR==1 && NR!=1 { while (/^<header>/) getline; }
    1 {print}
' file*.txt >all.txt

Awk script की पहली लाइन किसी फाइल की पहली लाइन ( FNR==1) से मेल खाती है, सिवाय इसके कि यह सभी फाइलों में पहली लाइन है ( NR==1)। जब इन शर्तों को पूरा किया जाता है, तो अभिव्यक्ति while (/^<header>/) getline;को निष्पादित किया जाता है, जो जागने का कारण बनता है एक और पंक्ति को पढ़ना जारी रखना (वर्तमान को छोड़ देना) जब तक कि वर्तमान एक regexp से मेल खाता है ^<header>। Awk script की दूसरी लाइन उन सभी लाइनों को प्रिंट करती है, जो पहले छोड़ी गई लाइनों को छोड़कर होती हैं।


धन्यवाद गिल्स। मेरी हर फाइल जीबी में है। कुशल यह नहीं होगा। इसीलिए मैंने पूछा।
जना

@ जान क्या ऐसी रेखाएँ हैं जो हेडर की तरह दिखती हैं लेकिन फ़ाइल के शीर्ष पर नहीं हैं? यदि नहीं, तो सबसे तेज़ तरीका उपयोग करना है grep(जैसे स्पुतनिक के उत्तर में )।
गिल्स एसओ- बुराई को रोकना '

कोई हेडर लाइनें सभी फाइलों के समान नहीं होती हैं और वे प्रत्येक फाइल के शीर्ष पर होती हैं। हाँ grep तेज था। आप दोनों को धन्यवाद
जना

1
@ जना, अगर आपकी सभी फ़ाइलों में हेडर लाइनों की संख्या समान है, तो यहां एक और तरीका है (जो मुझे और भी तेज़ होने की उम्मीद है): head -n 10 file1.txt >output.txt && tail -q -n +11 file*.txt >>output.txt(यदि आपके पास 10 हेडर लाइनें हैं)। इसके अलावा, यदि आपकी फ़ाइलों में उनके नाम में नंबर हैं, तो सावधान रहें कि और के file9.txtबीच में सॉर्ट किया गया है । आपकी फ़ाइलों संख्या की तरह है , ..., , , ..., तो उन्हें सही क्रम में सूची जाएगा। file89.txtfile90.txtfile001.txtfiles009.txtfiles010.txtfiles*.txt
गिल्स एसओ- बुराई को रोकना '

एक बेहतर समाधान ( stackoverflow.com/a/16890695/310441 से ) जिसे regex मिलान की आवश्यकता नहीं है: awk 'FNR==1 && NR!=1{next;}{print}' *.csv
Owen

42

एक और समाधान, cat+grepऊपर से " " के समान , उपयोग tailऔर head:

  1. आउटपुट में पहली फ़ाइल का हेडर लिखें:

    head -2 file1.txt > all.txt

    - head -2फ़ाइल की 2 पहली पंक्तियाँ प्राप्त करता है।

  2. सभी फ़ाइलों की सामग्री जोड़ें:

    tail -n +3 -q file*.txt >> all.txt

    - 3 से अंत तक प्रिंट लाइनें -n +3बनाता है tail, -qयह बताता है कि हेडर को फ़ाइल नाम (पढ़ें man) के साथ प्रिंट नहीं करना है, फ़ाइल में >>जोड़ता है, जैसा कि इसे अधिलेखित नहीं करता है >

और सुनिश्चित करें कि आप दोनों आदेशों को एक पंक्ति में रख सकते हैं:

head -2 file1.txt > all.txt; tail -n +3 -q file*.txt >> all.txt

या उनके बजाय सफलता की जाँच के लिए उनके बीच ;रखा &&


3
मैं इसे आगे बस करने का सुझाव देता हूं: (head -2 file1.txt ; tail -n +3 -q file*.txt ) > all.txtया(head -2 file1.txt && tail -n +3 -q file*.txt ) > all.txt
होंगझू

4

ऐसा करने का प्रयास करें:

$ cat file1.txt; grep -v "^<header" file2.txt
<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B 
C
D
E 
F

ध्यान दें

  • -vझंडा साधन के मैच को उलटने के लिए
  • ^में REGEX , साधन स्ट्रिंग की शुरुआत
  • यदि आपके पास फ़ाइलों का एक गुच्छा है, तो आप कर सकते हैं

:

array=( files*.txt )
{ cat ${array[@]:0:1}; grep -v "^<header" ${array[@]:1}; } > new_file.txt

यह ऐरे स्लाइसिंग तकनीक है।


धन्यवाद स्पुतनिक, लेकिन मेरे पास ~ 30 फाइलें (file1.txt, file2.txt, file3.txt..filen.txt) संक्षिप्त करने के लिए है। क्या मुझे हर फ़ाइल का नाम लिखना चाहिए या क्या कोई और तरीका है?
जन

टुकड़ा करने की तकनीक के साथ मेरी संपादित पोस्ट देखें
गाइल्स क्वेनोट

यह <header>फ़ाइलों में कहीं भी लाइनों को हटाता है , न कि केवल शुरुआत में। डेटा के आधार पर यह एक मुद्दा नहीं हो सकता है।
गिल्स एसओ- बुराई को रोकना '

1
सरल:grep '^<header>' file1.txt >output.txt && grep -v '^<header>' file*.txt >>output.txt
गिल्स एसओ- बुराई को रोकना '

@ गिल्स: मैंने लंबे समय के बाद आपके जवाब पर गौर किया लेकिन यह बहुत उपयोगी था
जन

1

tailआदेश (जीएनयू, कम से कम पर) प्रारंभिक लाइनों की दी गई संख्या को छोड़ने का विकल्प है। दूसरी पंक्ति से आगे की ओर प्रिंट करने के लिए, यानी एक-लाइन हेडर को छोड़ें, ऐसा करें:tail -n+2 myfile

तो, पहली फ़ाइल के दो-लाइन हेडर को रखने के लिए, लेकिन दूसरे को, बैश में नहीं:

cat file1.txt <(tail -n+3 file2.txt) > combined.txt

या, कई फ़ाइलों के लिए:

head -n1 file1.txt > combined.txt
for fname in *.txt
do
    tail -n+3 $fname >> combined.txt
done

यदि एक निश्चित स्ट्रिंग को सभी हेडर लाइनों में मौजूद होने के लिए जाना जाता है, लेकिन शेष इनपुट फ़ाइलों में कभी नहीं, grep -vएक सरल दृष्टिकोण है, जैसा कि स्पुतनिक ने दिखाया है।


1

छोटा (जरूरी नहीं कि तेज हो) sed:

sed -e '3,${/^<header>/d' -e '}' file*.txt > all.txt

यह <header>...लाइन 3 से शुरू होने वाली सभी लाइनों को हटा देगा , इसलिए पहला हेडर संरक्षित है और दूसरे हेडर हटा दिए गए हैं। अगर हेडर में अलग-अलग संख्या में लाइनें हैं, तो तदनुसार कमांड को समायोजित करें (उदाहरण के लिए 6-लाइन हेडर उपयोग 7के लिए 3)।
यदि शीर्ष लेख में पंक्तियों की संख्या अज्ञात है, तो आप इस तरह की कोशिश कर सकते हैं:

sed '1{
: again
n
/^<header>/b again
}
/^<header>/d
' file*.txt > all.txt

0

array = (* .txt); हेड -1 $ {array [0]}> all.txt; tail -n +2 -q $ {array [@]: 0} >> all.txt

मान लें कि आप एक ही हेडर के साथ .txt फ़ाइलों के साथ एक फ़ोल्डर का उपयोग कर रहे हैं जिसे संयुक्त / संक्षिप्त करने की आवश्यकता है, यह कोड सभी txt फ़ाइलों को सभी में जोड़ देगा । केवल एक हेडर के साथ। पहली पंक्ति (अर्धविराम द्वारा अलग की गई रेखाएँ) सभी पाठ फ़ाइलों को एकत्र करने के लिए इकट्ठा होती है , दूसरी पंक्तियाँ पहली txt फ़ाइल से हेडर को all.txt में आउटपुट करती है , और अंतिम पंक्ति हेडर के बिना एकत्रित की गई सभी टेक्स्ट फ़ाइलों को संक्षिप्त करती है (शुरू करके पंक्ति 2 के बाद से) और इसे all.txt में जोड़ता है ।


एक छोटा सा विवरण भविष्य के उपयोगकर्ताओं की मदद करने की दिशा में एक लंबा रास्ता तय करेगा
जेफ स्कालर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.