Aynı başlığa sahip birden fazla dosyayı birleştir


26

Aynı başlık ve altındaki farklı vektörler ile birden fazla dosya var. Hepsini birleştirmem gerekiyor, ancak yalnızca ilk dosyanın başlığının birleştirilmesini istiyorum ve diğer başlıkların hepsinin aynı olduğundan birleştirilmesini istemiyorum.

örneğin: dosya1.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

Çıktı olması gerekiyor

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

R'de bir script yazabilirim ama kabuğuna ihtiyacım var?

Yanıtlar:


17

R'de nasıl yapılacağını biliyorsanız, elbette R'de yapın. Klasik unix araçlarıyla, bu en doğal olarak awk olarak yapılır.

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

Awk betiğinin ilk satırı, FNR==1aynı zamanda tüm dosyalardaki ( NR==1) ilk satır olması dışında , bir dosyanın ilk satırıyla ( ) eşleşir . Bu koşullar yerine getirildiğinde, ifade while (/^<header>/) getline;yürütülür; bu, şu anki ifade regexp ile eşleştiği sürece awk'ın başka bir satırı okumaya devam etmesine (geçerli olanı atlayarak) devam etmesine neden olur ^<header>. Awk betiğinin ikinci satırı, daha önce atlanmış satırlar dışındaki her şeyi yazdırır.


Sağol Gilles. Dosyalarımın her biri GB’de. Bunu yapmak için R verimli olmayacak. Bu yüzden sordum.
Jana

@Jana Başlıklara benzeyen, ancak dosyanın üstünde olmayan çizgiler var mı? Değilse, en hızlı yol kullanmaktır grep( sputnik'in cevabında olduğu gibi ).
Gilles 'SO- kötülük'

Hiçbir başlık satırı tüm dosyalara benzemez ve bunlar sadece her dosyanın başındadır. Evet grep daha hızlıydı. İkinize de teşekkürler
Jana

1
@Jana Bu arada, eğer tüm dosyalarınız aynı sayıda başlık satırına sahipse, işte başka bir yol (daha hızlı olmasını beklerim): head -n 10 file1.txt >output.txt && tail -q -n +11 file*.txt >>output.txt(10 başlık satırınız varsa). Ayrıca, dosyalarınızın adlarında numaralar varsa, ve file9.txtarasında sıralananlara dikkat edin . Dosyalarınızı sayılar gibi varsa , ..., , , ..., daha sonra doğru sırayla listelenir. file89.txtfile90.txtfile001.txtfiles009.txtfiles010.txtfiles*.txt
Gilles 'SO- kötülük'

Düzenli eşleştirme gerektirmeyen daha iyi bir çözüm ( stackoverflow.com/a/16890695/310441 awk 'FNR==1 && NR!=1{next;}{print}' *.csv
Owen

42

cat+grepYukarıdan " " e benzer, başka bir çözüm kullanarak tailve head:

  1. İlk dosyanın başlığını çıktıya yazın:

    head -2 file1.txt > all.txt

    - head -2Dosyanın 2 ilk satırını alır.

  2. Tüm dosyaların içeriğini ekle:

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

    - 3. satırdan sonuna kadar yazdırma satırları -n +3yapar , başlığın dosya adıyla (okunmamış ) yazdırılmamasını söyler , üzerine yazmaz, dosyaya eklenir .tail-qman>>>

Ve her iki komutu da tek bir satıra yerleştirebileceğinizden emin olun:

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

veya başarı kontrolü için aralarında ;koymak yerine &&.


3
: Ben sadece bunu daha fazla önermek (head -2 file1.txt ; tail -n +3 -q file*.txt ) > all.txtveya(head -2 file1.txt && tail -n +3 -q file*.txt ) > all.txt
HongboZhu

4

Bunu yapmayı deneyin:

$ 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

NOT

  • -vbayrak aracının maçı ters çevirmek için
  • ^içinde REGEX , araçlar dize başlayan
  • eğer bir sürü dosyanız varsa,

:

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

Bir dizi dilimleme tekniğidir.


Teşekkürler sputnick, Ama birleştirmek için ~ 30 dosya (file1.txt, file2.txt, file3.txt..filen.txt) var. Her dosya adını mı yazmalıyım yoksa yapmanın başka yolları var mı?
Jana

Dilimleme tekniği ile düzenlenen yazıya bak
Gilles Quenot

Bu <header>, sadece başlangıçta değil, dosyaların herhangi bir yerinde satırları kaldırır . Bu, verilere bağlı olarak burada bir sorun olmayabilir.
Gilles 'SO- kötülük'

1
Basit:grep '^<header>' file1.txt >output.txt && grep -v '^<header>' file*.txt >>output.txt
Gilles 'KÖTÜ

@Gilles: Cevabınızı uzun zaman sonra fark ettim ama çok faydalı oldu
Jana

1

tail(GNU'da, en azından üzerine) komut ilk çizgiler belirli bir sayıda atlamak için bir seçenek vardır. İkinci satırdan itibaren yazdırmak, yani bir satırlık başlığı atlamak için:tail -n+2 myfile

Yani, ilk dosyanın iki satırlı başlığını ikinci sırada tutmak değil, Bash’de:

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

Veya birçok dosya için:

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

Belli bir dizginin tüm başlık satırlarında bulunduğu, ancak hiçbir zaman giriş dosyalarının geri kalanında bulunmadığı biliniyorsa grep -v, sputnik'in gösterdiği gibi basit bir yaklaşımdır.


1

Daha kısa olan (mutlaka daha hızlı değil) sed:

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

Bu, <header>...3. satırdan başlayarak başlayan tüm satırları siler , böylece ilk başlık korunur ve diğer başlıklar kaldırılır. Başlıkta farklı sayıda satır varsa komutu buna göre ayarlayın (örneğin, 7yerine 6 satırlık başlık kullanımı için 3).
Başlıktaki satır sayısı bilinmiyorsa, aşağıdakileri deneyebilirsiniz:

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

0

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

Birleştirilmesi / birleştirilmesi gereken aynı başlığa sahip .txt dosyaları içeren bir klasör kullandığınızı varsayarsak, bu kod tüm txt dosyalarını all.txt içinde tek bir başlıkla birleştirir. ilk satır (noktalı virgüllerle ayrılmış satırlar) tüm metin dosyalarını birleştirilecek şekilde toplar, ikinci satırlar başlığı ilk txt dosyasından all.txt dosyasına çıkarır ve son satır, başlık olmadan toplanan tüm metin dosyalarını birleştirir (başlayarak satır 2'den itibaren bitiştirme) ve all.txt dosyasına ekler .


ufak bir açıklama gelecekteki kullanıcılara yardım etme yolunda uzun bir yol kat edecek
Jeff Schaller
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.