J'ai plusieurs fichiers avec le même en-tête et différents vecteurs en dessous. J'ai besoin de les concaténer tous, mais je veux que l'en-tête du premier fichier soit concaténé et je ne veux pas que les autres en-têtes soient concaténés car ils sont tous les mêmes.
par exemple: 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
J'ai besoin que la sortie soit
<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B
C
D
E
F
Je pourrais écrire un script en R mais j'en ai besoin en shell?
grep
(comme dans la réponse de Spoutnik ).head -n 10 file1.txt >output.txt && tail -q -n +11 file*.txt >>output.txt
(si vous avez 10 lignes d'en-tête). De plus, si vos fichiers ont des numéros dans leurs noms, méfiez-vous quifile9.txt
est trié entrefile89.txt
etfile90.txt
. Si vos fichiers ont de tels chiffresfile001.txt
, ...,files009.txt
,files010.txt
, ..., puisfiles*.txt
leur liste dans l'ordre.awk 'FNR==1 && NR!=1{next;}{print}' *.csv
Une autre solution, similaire à "
cat+grep
" ci-dessus, utilisanttail
ethead
:Écrivez l'en-tête du premier fichier dans la sortie:
-
head -2
obtient les 2 premières lignes du fichier.Ajoutez le contenu de tous les fichiers:
-
-n +3
créetail
des lignes d'impression du 3ème à la fin, lui-q
dit de ne pas imprimer l'en-tête avec le nom du fichier (luman
),>>
ajoute au fichier, ne le remplace pas par>
.Et bien sûr, vous pouvez mettre les deux commandes sur une seule ligne:
ou au lieu de les
;
mettre&&
entre eux pour vérifier le succès.la source
(head -2 file1.txt ; tail -n +3 -q file*.txt ) > all.txt
ou(head -2 file1.txt && tail -n +3 -q file*.txt ) > all.txt
Essayez de faire ceci:
REMARQUE
-v
drapeau signifie inverser le match de grep^
dans REGEX , signifie début de la chaîne:
C'est une technique de découpage de tableau bash .
la source
<header>
lignes n'importe où dans les fichiers, pas seulement au début. Cela peut ne pas être un problème ici, selon les données.grep '^<header>' file1.txt >output.txt && grep -v '^<header>' file*.txt >>output.txt
La
tail
commande (sur GNU, au moins) a une option pour ignorer un nombre donné de lignes initiales. Pour imprimer à partir de la deuxième ligne, c'est-à-dire sauter un en-tête d'une ligne, procédez comme suit:tail -n+2 myfile
Donc, pour garder l'en-tête à deux lignes du premier fichier mais pas du second, dans Bash:
Ou, pour de nombreux fichiers:
Si une certaine chaîne est connue pour être présente dans toutes les lignes d'en-tête mais jamais dans le reste des fichiers d'entrée,
grep -v
c'est une approche plus simple, comme l'a montré sputnik.la source
Plus court (pas nécessairement plus rapide) avec
sed
:Cela supprimera toutes les lignes
<header>...
commençant par la ligne 3, donc le premier en-tête est conservé et les autres en-têtes sont supprimés. S'il y a un nombre différent de lignes dans l'en-tête, ajustez la commande en conséquence (par exemple pour un en-tête à 6 lignes, utilisez7
plutôt que3
).Si le nombre de lignes dans l'en-tête est inconnu, vous pouvez essayer comme ceci:
la source
En supposant que vous utilisez un dossier avec des fichiers .txt avec le même en-tête qui doivent être combinés / concaténés, ce code combinerait tous les fichiers txt dans all.txt avec un seul en-tête. la première ligne (lignes séparées par des points-virgules) rassemble tous les fichiers texte à concaténer, les secondes lignes sortent l'en-tête du premier fichier txt dans all.txt et la dernière ligne concatène tous les fichiers texte rassemblés sans l'en-tête (en démarrant le concaténation à partir de la ligne 2) et l'ajoute à all.txt .
la source