web-dev-qa-db-fra.com

Utilisez sed pour remplacer le dernier espace de chaque ligne par une virgule, puis supprimez tous les espaces.

J'ai un fichier .txt à deux colonnes, délimité par des espaces, mais la première colonne contient des espaces (qui sont des erreurs). Je dois le convertir en csv, mais je ne peux pas simplement remplacer tous les espaces par des virgules.

Exemple d'entrée:

gi|118592783|ref|ZP_01550172.1|_biphenyl-2  3-diol_1    2-dioxygenase_[Stappia_aggregata_IAM_12614] 1

Sortie désirée:

gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1

Comment utiliser sed (ou quoi que ce soit d'autre) pour remplacer le dernier espace d'une ligne par une virgule, puis supprimer tous les espaces restants? Cela créerait-il efficacement un fichier CSV?

7
Zoey RW

Quelque chose comme:

sed -r 's/(.*) /\1,/; s/ //g'

La première substitution, étant gourmande, couvrira tout sauf la dernière place du groupe, en remplaçant la dernière par un ,. La seconde éliminera ensuite le reste.

8
muru

Cela ferait le travail:

sed -r "s/\s([0-9]+$)/,\1/" filename.txt | tr -d ' '

ou:

sed -r "s/\s([0-9]+$)/,\1/; s/\s//g" filename.txt

Exemple d'entrée:

gi|118592783|ref|ZP_01550172.1|_biphenyl-2 3-diol_1    2-dioxygenase_[Stappia_aggregata_IAM_12614] 1

Sortie:

gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1
3
Ravexina

Voici une façon geek - avec une boucle sed.

  1. si le motif ne contient qu'un seul espace, remplacez-le par une virgule
  2. (sinon) remplace le premier espace par rien et passe à 1

que nous pouvons écrire dans GNU sed comme

sed -e :1 -e '/^[^ ]* [^ ]*$/ s/ /,/' -e 's/ //; t1'

Essai:

$ echo 'gi|118592783|ref|ZP_01550172.1|_biphenyl-2  3-diol_1    2-dioxygenase_[Stappia_aggregata_IAM_12614] 1' | 
  sed -e :1 -e '/^[^ ]* [^ ]*$/ s/ /,/' -e 's/ //; t1'
gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1
3
steeldriver

Perl

$ Perl -ne 's/\s//g;s/^(.*)([[:digit:]])$/\1,\2/;print' input.txt                                                                                    
gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1

ou plus court:

Perl -pe 's/\s//g;s/^(.*)([[:digit:]])$/\1,\2/' input.txt 

Effectivement, c'est l'inverse de l'approche de muru: nous supprimons tout d'abord les espaces, puis nous regroupons tout avant le dernier élément (groupe \1) et le dernier élément (groupe \2, deux qui se trouve être numérique). Nous remplaçons la ligne par le groupe \1 et \2 séparés par une virgule.

Notez que ([[:digit:]]) peut être changé en (.) pour référencer n’importe quel caractère, le cas échéant (c’est-à-dire si nous nous attendons à ce que le dernier caractère soit de tout type), ou nous pouvons utiliser ([[:graph:]]) pour traiter uniquement les caractères imprimables.

3