45
votes

Convertir toutes les abréviations du nombre en valeurs numériques dans un fichier texte

Je voudrais convertir toutes les abréviations du nombre telles que 1K, 100K, 1M, etc. dans un fichier texte en valeurs numériques simples telles que 1000, 100000, 1000000, etc.

Ainsi, par exemple, si j'ai Le fichier texte suivant:

sed -e 's/1K/1000/g' -e 's/1M/1000000/g' text-file.txt

Je voudrais le convertir en ce qui suit en bash:

1300 apples
87900 oranges
156000 mangos
541700 carrots
1800000 potatoes

La commande I avoir utilisé est de remplacer les chaînes de correspondance des abréviations du nombre par leurs valeurs numériques complètes comme ça:

1.3K apples
87.9K oranges
156K mangos
541.7K carrots
1.8M potatoes

Mon problème est que je ne trouve pas et remplace toutes les abréviations du nombre possibles lorsque la variation se produit. Je voudrais le faire jusqu'à au moins jusqu'à une décimale.

.


0 commentaires

9 Réponses :


28
votes

Pourriez-vous s'il vous plaît essayer de suivre, écrit et testé avec des échantillons affichés dans GNU awk .

1300 apples
87900 oranges
156000 mangos
541700 carrots
1800000 potatoes

Explication: ajout d'explication détaillée pour ci-dessus.

awk '                     ##Starting awk program from here.
{
  if(sub(/[kK]$/,"",$1)){ ##Checking condition if 1st field ends with k/K then do following. Substituting k/K in first field with NULL here.
    $1*=1000              ##Multiplying 1000 with current 1st field value here.
  }
  if(sub(/[mM]$/,"",$1)){ ##Checking condition if 1st field ends with m/M then do following. Substituting m/M in first field with NULL here.
    $1*=1000000          ##Multiplying 1000000 with current 1st field value here.
  }
}
1                         ##1 will print current line here.
' Input_file              ##Mentioning Input_file name here.


0 commentaires

16
votes

une autre variante awk :

awk '{q = substr($1, length($1));
$1 *= (q == "M" ? 1000000 : (q=="K"?1000:1))} 1' file

1300 apples
87900 oranges
156000 mangos
541700 carrots
1800000 potatoes


0 commentaires

16
votes

Cela effectue une substitution globale (au cas où vous avez> 1 chaîne à convertir par ligne):

perl -pe 's{\b(\d+(?:\.\d+)?)([KM])\b}{ $1*1000**(index("KM",$2)+1) }ge' file


0 commentaires


8
votes

d'une manière un peu plus de programmation, et basé sur cette réponse , vous pouvez créer une liste de toutes possibles possibles Facteurs de conversion et préformez les multiplications en cas de besoin:

awk 'BEGIN{f["K"]=1000; f["M"]=1000000}
     match($1,/[a-zA-Z]+/){$1 *= f[substr($1,RSTART,RLENGTH)]}
     1' file


0 commentaires

6
votes

Étant donné:

1,300 apples
87,900 oranges
156,000 mangos
541,700 carrots
1,800,000 potatoes


0 commentaires

7
votes

Une autre option peut être d'utiliser Bash uniquement et un modèle avec la capture de groupes, où vous captureriez m ou k . Si le motif correspond, testez l'un d'eux et définissez le multiplicateur et utilisez bc

1300 apples
87900 oranges
156000 mangos
541700 carrots
1800000 potatoes

output

while IFS= read -r line
do
  if [[ $line =~ ^([[:digit:]]+(\.[[:digit:]]+)?)([MK])( .*)$ ]];then
    echo "$(bc <<< "${BASH_REMATCH[1]} * $([ ${BASH_REMATCH[3]} == "K" ] && echo "1000" || echo "1000000") / 1")${BASH_REMATCH[4]}"
  fi
done < text-file.txt
Bash Demo


0 commentaires

7
votes

avec gnu awk pour gensub ():

$ awk '
    BEGIN { mult[""]=1; mult["k"]=1000; mult["m"]=100000 }
    { $1 *= mult[gensub(/[^[:alpha:]]/,"","g",tolower($1))] }
1' file
1300 apples
87900 oranges
156000 mangos
541700 carrots
180000 potatoes


0 commentaires

6
votes

Cela pourrait fonctionner pour vous (GNU SED):

sed -E '1{x;s/^/K00M00000/;x}
        :a;G;s/([0-9])(\.([0-9]))?([KM])(.*)\n.*\4(0*).*/\1\3\6\5/i;ta
        P;d' file

Créez une recherche et stockez-la dans l'espace de maintien.

Ajoutez la recherche de chaque ligne et utilisez correspondance du motif pour remplacer les touches dans la recherche par sa valeur.

Imprimez enfin la ligne lorsqu'aucune autre correspondance n'est trouvée.


0 commentaires