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.
.
9 Réponses :
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.
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
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
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
Étant donné:
1,300 apples 87,900 oranges 156,000 mangos 541,700 carrots 1,800,000 potatoes
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.txtBash Demo
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
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.