Comment puis-je tout supprimer après le deuxième deux-points de la deuxième colonne et conserver tout le reste?

Nov 19 2020

J'ai un fichier ( file.bim) avec environ 1,5 million. lignes qui ressemblent à ceci:

1   1:819959:C:T    0   819959  T   C
1   1:821249:G:A    0   821249  A   G
1   1:821477:A:G    0   821477  G   A
1   1:821843:C:T    0   821843  T   C
1   1:823963:A:C    0   823963  C   A
1   1:824357:C:T    0   824357  T   C
1   1:824398:A:C    0   824398  C   A
1   1:827972:G:A    0   827972  A   G
1   1:828539:A:T    0   828539  T   A

Dans la deuxième colonne, je voudrais supprimer le deuxième deux-points et les trois caractères suivants, et conserver les colonnes restantes telles quelles. La sortie souhaitée est la suivante ( updated_file.bim):

1   1:819959    0   819959  T   C
1   1:821249    0   821249  A   G
1   1:821477    0   821477  G   A
1   1:821843    0   821843  T   C
1   1:823963    0   823963  C   A
1   1:824357    0   824357  T   C
1   1:824398    0   824398  C   A
1   1:827972    0   827972  A   G
1   1:828539    0   828539  T   A

J'ai essayé d'utiliser awk, mais ici seuls les deux points sont supprimés, mais les lettres entre eux restent:

awk -F":" '{ print $1":"$2,$3,$4,$5,$6 }' file.bim > updated_file.bim

Réponses

2 AdminBee Nov 19 2020 at 18:20

Vous pouvez utiliser le awkprogramme suivant :

awk '{sub(/:[^:]*:[^:]*$/,"",$2)}1' file.bim > updated_file.bim

ou

awk '{sub(/(:[^:]*){2}$/,"",$2)}1' file.bim > updated_file.bim

Cela utilisera la sub()fonction pour éditer la deuxième colonne ( $2) en remplaçant les deux dernières :et le texte qui les suit par "rien", supprimant ainsi effectivement cette partie.

Si le fichier de sortie doit être séparé par des tabulations, utilisez awk -v OFS="\t" ' ... '.

Sinon , si votre fichier est délimité par des groupes de plus d'un «espace» et que vous voulez vous assurer que la mise en forme du délimiteur est complètement inchangée, vous pouvez utiliser

awk '{sub(/:[^:]*:[^: ]* /," ")}1' file.bim > updated_file.bim

qui recherchera le motif " :, suivi du texte, suivi de :, suivi du texte, suivi de l'espace", et remplacera celui-ci par un seul "espace". Dans votre entrée, ce modèle se produit uniquement à la fin de la colonne 2, de sorte que le remplacement n'affectera que cette colonne.

Enfin , si à tout moment dans le futur le nombre de :champs séparés dans la deuxième colonne peut changer, mais que vous ne voulez toujours conserver que les deux premiers, vous pouvez recourir à ma variante originale bien que moins portable, qui remplace la deuxième colonne par seulement le texte autour du premier :(au lieu du texte derrière les deux derniers avec "rien"):

awk '{$2=gensub(/([^:]+:[^:]+).*/,"\\1","1",$2)}1' file.bim > updated_file.bim
2 αғsнιη Nov 19 2020 at 18:45

Supprimez tout après le deuxième deux-points dans la deuxième colonne et conservez tout le reste:

awk '{ c=split($2, s, ":"); $2=s[1] (c>1?":":"") s[2]; }1' infile

comme vous l'avez remarqué, cela supprime les espaces répétés lorsque nous réévaluons la deuxième colonne si ce n'est pas le gros problème de votre côté; sinon utilisez ci-dessous sedcomme alternative:

sed -E 's/^([^ ]* *)([^: ]*:[^: ]*):[^ ]* (.*)/\1\2 \3/' infile

date du test;

::1   1:81995:9:C:T    0   8::199:59  T   C
1:a:  :1821249GA:    0   821:2:4  A   G
111   1:828539::    0   :::828539  T   A

résultat:

::1   1:81995    0   8::199:59  T   C
1:a:  :1821249GA    0   821:2:4  A   G
111   1:828539    0   :::828539  T   A
1 EdMorton Nov 20 2020 at 06:59

Avec GNU sed pour \S:

$ sed 's/\(:[^:]*\)\S*/\1/' file
1   1:819959    0   819959  T   C
1   1:821249    0   821249  A   G
1   1:821477    0   821477  G   A
1   1:821843    0   821843  T   C
1   1:823963    0   823963  C   A
1   1:824357    0   824357  T   C
1   1:824398    0   824398  C   A
1   1:827972    0   827972  A   G
1   1:828539    0   828539  T   A

ou avec n'importe quel sed POSIX:

$ sed 's/\(:[^:]*\)[^[:space:]]*/\1/' file
1   1:819959    0   819959  T   C
1   1:821249    0   821249  A   G
1   1:821477    0   821477  G   A
1   1:821843    0   821843  T   C
1   1:823963    0   823963  C   A
1   1:824357    0   824357  T   C
1   1:824398    0   824398  C   A
1   1:827972    0   827972  A   G
1   1:828539    0   828539  T   A
RedaSalih Nov 19 2020 at 18:07

Utilisez sed pour remplacer tous les espaces vides par ":" puis ignorez les champs $ 6 et $ 7 et mettez le contenu de 4 $ et 5 $ sur 5 $ avec awk:

sed  's/ /:/g' bim | awk  -F':' '{ $6=""; $7="" ; $4=$4$5; $5="" }1' > updated_file.bim 

SANS SED:

awk  '{ gsub(/ /,":",$0); FS=":";$6=""; $7="" ; $4=$4$5; $5="" }1' bim > updated_file.bim 
CarlosPascual Nov 19 2020 at 19:05

avec d' awkabord avec substr($2, 1, 8)vous sélectionnez à partir de 2 $ ce dont vous avez besoin. Et imprimez la valeur de sau lieu de $2. Donc, votre code avec ceci peut être:

awk 's = substr($2, 1, 8) {print $1, s, $3, $4, $5, $6}' file
1 1:819959 0 819959 T C
1 1:821249 0 821249 A G
1 1:821477 0 821477 G A
1 1:821843 0 821843 T C
1 1:823963 0 823963 C A
1 1:824357 0 824357 T C
1 1:824398 0 824398 C A
1 1:827972 0 827972 A G
1 1:828539 0 828539 T A

Mis à jour, pour garder les espaces:

awk -F '[[:blank:]]{2,}' '$2 = substr($2, 1, 8) {print $1, $2, $3, $4, $5, $6}' file | column -t
1  1:819959  0  819959  T  C
1  1:821249  0  821249  A  G
1  1:821477  0  821477  G  A
1  1:821843  0  821843  T  C
1  1:823963  0  823963  C  A
1  1:824357  0  824357  T  C
1  1:824398  0  824398  C  A
1  1:827972  0  827972  A  G
1  1:828539  0  828539  T  A
codeholic24 Nov 19 2020 at 19:16

La sortie suivante peut être obtenue à l'aide de la sedcommande

cat file.bim | sed 's/:[a-zA-Z]//g' >> updated_file.bim

or

cat file.bim | sed 's/:[[:alpha:]]//g' >> updated_file.bim

Production :

1   1:819959    0   819959  T   C
1   1:821249    0   821249  A   G
1   1:821477    0   821477  G   A
1   1:821843    0   821843  T   C
1   1:823963    0   823963  C   A
1   1:824357    0   824357  T   C
1   1:824398    0   824398  C   A
1   1:827972    0   827972  A   G
1   1:828539    0   828539  T   A