2
votes

Remplacement de numéros dans la même plage

J'ai un fichier de délimitation de tabulation1 où la première colonne ressemble à

sed -e 's/a/b/g ; s/b/d/g' file

Je veux le remplacer pour que 1 = 1, 1A = 2, 1B = 3, 2 = 4, 3 = 5, 4 = 6, 4A = 7, 6 = 8, Z = 9 La sortie devrait alors être

1
1
8
8
8
2
2
3
4
4
4
4
5
6
7
9
9

J'ai envoyé d'autres articles disant que pour éviter les substitutions cumulatives, je devrais passer de plus grandes valeurs à des plus petites et faire les substitutions multiples en utilisant:

1
1
6
6
6
1A
1A
1B
2
2
2
2
3
4
4A
Z
Z

mais j'ai 60 substitutions à faire.

Y a-t-il un moyen de faire cela en boucle ou une autre alternative au lieu d'écrire 60 substitutions

Notez que chaque élément est répété plusieurs fois et qu'il peut s'agir de nombres et de caractères, Je les remplace tous par les numéros 1 à 60, et dans un ordre prédéfini et non dans l'ordre dans lequel ils apparaissent. Mon fichier a d'autres colonnes avec les mêmes caractères, mais je veux seulement remplacer des choses dans la 1ère colonne.


4 commentaires

Vous allez devoir créer un mappage entre les anciennes et les nouvelles valeurs, quelle que soit la solution avec laquelle vous vous retrouvez, alors j'écrirais simplement les 60 substitutions et j'en aurais terminé.


D'accord! Mieux vaut commencer alors. Thxs


Votre description 1 = 1, 1A = 2, 1B = 3, 2 = 4, 3 = 5, 4 = 6, 4A = 7, 6 = 8, Z = 9 n'explique pas comment < code> 6 dans l'entrée devient 4 dans la sortie. Assurez-vous que votre description correspond à votre exemple et assurez-vous également que votre exemple comprend des cas qui pourraient être perturbés si la traduction se produit dans le mauvais ordre.


Erreur de frappe corrigée. Merci d'avoir remarqué.


5 Réponses :


3
votes

Créez un fichier de mappage avec vos chaînes de recherche et de remplacement comme:

1
1
8
8
8
2
2
3
4
4
4
4
5
6
7
9
9

Ensuite, utilisez simplement ce awk pour obtenir toutes les substitutions en une seule commande:

awk 'BEGIN{FS=OFS="\t"} NR == FNR{key[$1]=$2; next} $1 in key{$1=key[$1]} 1' mapping file

cat mapping
1   1
1A  2
1B  3
2   4
3   5
4   6
4A  7
6   8
Z   9


0 commentaires

1
votes

Pourriez-vous s'il vous plaît essayer ce qui suit (ajoutez FS = OFS = "\ t" supplémentaire dans la section BEGIN au cas où vous auriez un fichier d'entrée séparé par TAB et que vous auriez également besoin d'une sortie dans TAB formulaire).

awk '
BEGIN{
  key="1,1A,1B,2,3,4,4A,6,Z"
  value="1,2,3,4,5,6,7,8,9"
  split(key,array1,",")
  num=split(value,array2,",")
  for(i=1;i<=num;i++){
    pair[array1[i]]=array2[i]
  }
}
{
  for(i=1;i<=NF;i++){
    if($i in pair){
      $i=pair[$i]
    }
  }
}
1
'   Input_file


0 commentaires

1
votes

pour le préfixe à un seul chiffre, cela fonctionnera sans mappage manuel

$ awk 'NR==FNR {a[$1]; next} 
       FNR==1  {asorti(a,b); for(k in b) c[b[k]]=k} 
               {print c[$1]}' file{,}

1
1
8
8
8
2
2
3
4
4
4
4
5
6
7
9
9

notez que 6 est mappé sur 8, et non sur 4 comme dans votre exemple de sortie.


0 commentaires

1
votes

Cela pourrait fonctionner pour vous (GNU sed):

sed -E 's/$/\n:1=1:1A=2:1B=3:2=4:3=5:4=6:4A=7:6=8:Z=9/;s/^(\S+)(.*)\n.*:\1=([^:]*).*/\3\2/;P;d' file

Ajoutez une table de recherche à chaque ligne et utilisez la correspondance de modèle et les références arrière pour traduire la première colonne en la chaîne requise. p>

NB Les lignes qui n'ont pas de recherche correspondante ne seront pas modifiées.


0 commentaires

1
votes

Puisque vous voulez simplement utiliser des nombres consécutifs commençant à 1 comme remplacements, tout ce dont vous avez besoin est:

awk '
BEGIN {
    split("1 1A 1B 2 3 4 4A 6 Z",tmp)
    for (i in tmp) {
        map[tmp[i]] = i
    }
    FS = OFS = "\t"
}
$1 in map { $1 = map[$1] }
1' file
1
1
8
8
8
2
2
3
4
4
4
4
5
6
7
9
9
1


0 commentaires