it-swarm.com.de

Verketten Sie mehrere Dateien mit demselben Header

Ich habe mehrere Dateien mit dem gleichen Header und verschiedenen Vektoren darunter. Ich muss alle verketten, aber ich möchte, dass nur der Header der ersten Datei verkettet wird, und ich möchte nicht, dass andere Header verkettet werden, da sie alle gleich sind.

zum Beispiel: 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

Ich muss die Ausgabe sein

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

Ich könnte ein Skript in R schreiben, aber ich brauche es in der Shell?

29
Jana

Wenn Sie wissen, wie man es in R macht, dann machen Sie es auf jeden Fall in R. Mit klassischen Unix-Tools wird dies am natürlichsten in awk gemacht.

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

Die erste Zeile des awk-Skripts entspricht der ersten Zeile einer Datei (FNR==1), Es sei denn, es ist auch die erste Zeile aller Dateien (NR==1). Wenn diese Bedingungen erfüllt sind, wird der Ausdruck while (/^<header>/) getline; ausgeführt, wodurch awk eine weitere Zeile liest (die aktuelle überspringt), solange die aktuelle mit dem regulären Ausdruck ^<header> Übereinstimmt. Die zweite Zeile des awk-Skripts druckt alles außer den zuvor übersprungenen Zeilen.

Eine andere Lösung, ähnlich wie "cat+grep "von oben mit tail und head:

  1. Schreiben Sie den Header der ersten Datei in die Ausgabe:

    head -2 file1.txt > all.txt
    

    - head -2 erhält 2 erste Zeilen der Datei.

  2. Fügen Sie den Inhalt aller Dateien hinzu:

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

    - -n +3 macht tail Druckzeilen vom 3. bis zum Ende, -q weist an, den Header nicht mit dem Dateinamen zu drucken (lesen Sie man), >> fügt der Datei hinzu und überschreibt sie nicht als >.

Und sicher können Sie beide Befehle in eine Zeile setzen:

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

oder anstelle von ; stellen && zwischen ihnen zur Erfolgskontrolle.

44
xealits

Versuchen Sie Folgendes:

$ 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

HINWEIS

  • das -v flag bedeutet, die Übereinstimmung von grep zu invertieren
  • ^ in REGEX bedeutet den Beginn der Zeichenfolge
  • wenn Sie eine Reihe von Dateien haben, können Sie dies tun

::

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

Es ist eine bash Array-Slicing-Technik.

4
Gilles Quenot

Kürzer (nicht unbedingt schneller) mit sed:

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

Dadurch werden alle Zeilen gelöscht, die mit <header>... Ab Zeile 3 beginnen, sodass der erste Header erhalten bleibt und die anderen Header entfernt werden. Wenn der Header eine andere Anzahl von Zeilen enthält, passen Sie den Befehl entsprechend an (z. B. verwenden Sie für einen 6-Zeilen-Header 7 Anstelle von 3).
Wenn die Anzahl der Zeilen in der Kopfzeile unbekannt ist, können Sie Folgendes versuchen:

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

Der Befehl tail (zumindest auf GNU) bietet die Option, eine bestimmte Anzahl von Anfangszeilen zu überspringen. Um ab der zweiten Zeile zu drucken, d. H. Einen einzeiligen Header zu überspringen, gehen Sie wie folgt vor: tail -n+2 myfile

Um den zweizeiligen Header der ersten, aber nicht der zweiten Datei in Bash beizubehalten:

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

Oder für viele Dateien:

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

Wenn bekannt ist, dass eine bestimmte Zeichenfolge in allen Kopfzeilen vorhanden ist, jedoch niemals in den übrigen Eingabedateien, grep -v ist ein einfacherer Ansatz, wie Sputnik gezeigt hat.

1
etal

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

Angenommen, Sie verwenden einen Ordner mit TXT-Dateien mit demselben Header, der kombiniert/verkettet werden muss, würde dieser Code die TXT-Dateien alle in all.txt mit nur einem Header kombinieren. Die erste Zeile (durch Semikolons getrennte Zeilen) sammelt alle zu verkettenden Textdateien, die zweite Zeile gibt den Header aus der ersten txt-Datei in all.txt aus und die letzte Zeile verkettet alle gesammelten Textdateien ohne den Header (durch Starten der Verkettung ab Zeile 2) und hängt ihn an all.txt an.

0
Eric