2017-09-22 1 views
1

Je cherche à faire des suppressions dans un fichier de données à des positions spécifiques dans des lignes spécifiques, basé sur une liste dans un fichier texte séparé, et ont eu du mal à comprendre. Je travaille dans cygwin, et j'ai un (généralement grand) fichier de données (data_file) pour faire les suppressions, et un fichier texte délimité par des tabulations (coords_file) énumérant les numéros de ligne pertinents dans la colonne 2 et l'appariement En fait, je pense que j'essaie de faire quelque chose de similaire à la commande sed incomplète suivante, où coords_file $ 2 représente le numéro de ligne de la deuxième colonne de coords_file et de coords_file $ 3 représente la position sur cette ligne à supprimer.Utilisation de sed ou awk (ou similaire) incrémentalement ou avec une boucle pour faire des suppressions dans un fichier de données basé sur des lignes et des numéros de position donnés dans un autre fichier texte

sed -r 's coords_file$2/(.{coords_file$3}).*/\1/' datafile  

Je me demande s'il y a un moyen d'inclure une boucle ou itération de telle sorte que fonctionne sed d'abord en utilisant les valeurs de la première rangée de coords_file pour remplir la ligne correspondante et coordonnées de position, puis fonctionne à nouveau en utilisant les valeurs de la deuxième ligne, etc. pour toutes les lignes dans coords_file? Ou s'il y a une autre approche, par ex. en utilisant awk pour atteindre le même résultat?

par exemple. pour awk, j'ai identifié ces coordonnées basées sur des chaînes de caractères en utilisant cette commande awk très pratique de la réponse d'Ed Morton à cette question: line and string position of grep match.

awk 'NR==FNR{strings[$0]; next} {for (string in strings) if ((idx = index($0,string)) > 0) print string, FNR, idx }' strings.txt data_file > coords_file.txt 

Pensais potentiellement quelque chose de semblable pourrait faire travailler une suppression en place plutôt que de trouver les lignes, comme incorporant une trouvaille simple et remplacer comme {if($0=="somehow_reference_coords_file_values_here"){$0=""}. Mais c'est un peu hors de moi (je suis un novice en codage, donc je comprends à peine comment cette commande originale fonctionne, et encore moins comment la modifier).

exemples du fichier

de data_file

@vandelay.1 
blablablablablablablablablablablabla 
+ 
mehmehmehmehmehmehmehmehmehmehmehmeh 
@vandelay.2 
blablablablablablablablablablablabla 
+ 
mehmehmehmehmehmehmehmehmehmehmehmeh 
@vandelay.3 
blablablablablablablablablablablabla 
+ 
mehmehmehmehmehmehmehmehmehmehmehmeh 

coords_file (délimité par des tabulations)
(colonne 1 se trouve la chaîne de caractères qui a été adaptée, la colonne 2 est le numéro de la ligne, il correspond à, et la colonne 3 est le numéro de position du match).

stringID 2 20 
stringID 4 20 
stringID 10 27 
stringID 12 27 

Résultat souhaité:

@vandelay.1 
blablablablablablab 
+ 
mehmehmehmehmehmehm 
@vandelay.2 
blablablablablablablablablablablabla 
+ 
mehmehmehmehmehmehmehmehmehmehmehmeh 
@vandelay.3 
blablablablablablablablabl 
+ 
mehmehmehmehmehmehmehmehme 

Toute orientation serait très apprécié merci! (Et comme je l'ai mentionné, je suis très nouveau à cette scène de codage, donc des excuses si certains de cela n'a pas de sens ou shonky de mon format de question (ou si la question elle-même est rudimentaire)).

Cheers.

(Soit dit en passant, cela a été un énorme travail autour de supprimer des chaînes identifiées dans les blablabla lignes de data_file ainsi que les mêmes positions 2 lignes ci-dessous (par exemple les mehmehmeh lignes), puisque les mehmehmeh personnages sont des scores de qualité qui correspondent les blablabla caractères pour chaque échantillon (chaque @vandelay.xx). Essentiellement ceci: sed -i 's/string.*//' datafile, mais en exécutant la même suppression 2 lignes ci-dessous chaque fois qu'il identifie la chaîne.Donc, s'il y a en fait un script plus facile à faire simplement qu'au lieu de toutes les choses dans la question ci-dessus, s'il vous plaît laissez-moi savoir!)

+1

La réponse ci-dessous ressemble comme une solution pour votre problème décrit, .... mais si cela est plus qu'une solution unique, je l'espère vraiment que vous allez revenir en arrière et fixer vos processus de production. Cela ne fera qu'empirer si vous laissez cela en place (à partir de l'expérience personnelle/observation; - /). Bonne chance. – shellter

+0

Merci pour la réponse @shelter. Ouais, la réponse de CWLiu était parfaite. J'espère que c'est en effet un peu un! Mais va trouver comment faire marche arrière et le réparer plus tôt si c'est une chose en cours;). À votre santé. –

Répondre

2

Vous pouvez simplement utiliser une doublure awk pour le faire,

$ awk 'NR==FNR{a[$2]=$3;next} (FNR in a){$0=substr($0,0,a[FNR]-1)}1' coords_file data_file 
@vandelay.1 
blablablablablablab 
+ 
mehmehmehmehmehmehm 
@vandelay.2 
blablablablablablablablablablablabla 
+ 
mehmehmehmehmehmehmehmehmehmehmehmeh 
@vandelay.3 
blablablablablablablablabl 
+ 
mehmehmehmehmehmehmehmehme 

bref explication,

  • NR==FNR{a[$2]=$3;next}: créer le numéro de ligne et la carte de position correspondante dans le tableau a. Cette partie de l'expression traiterait seulement coords_file en raison de NR==FNR
  • (FNR in a): alors awk commencerait à traiter data_file. Utilisez l'expression pour rechercher n'importe quel fichier FNR contenu dans le tableau a.
  • $0=substr($0,0,a[FNR]-1): réaffectez le $0 à la ligne à couper.
  • 1: imprimer toutes les lignes
+0

Légende. C'est parfait merci. Je n'ai pas le représentant pour aller voter désolé, mais c'est sur place. –

+0

Et merci pour l'explication détaillée ainsi btw. Je n'ai pas d'arrière-plan de codage, donc ce genre d'explication m'aide à comprendre ce qui se passe réellement dans les commandes. À votre santé. –

+0

De rien. Content que cela puisse aider. – CWLiu