将文本文件中的所有数字缩写转换为数值

yfjy0ee7  于 2021-06-26  发布在  Impala
关注(0)|答案(9)|浏览(540)

我想将文本文件中的所有数字缩写(如1k、100k、1m等)转换为纯数字值(如1000、100000、1000000等)。
例如,如果我有以下文本文件:

  1. 1.3K apples
  2. 87.9K oranges
  3. 156K mangos
  4. 541.7K carrots
  5. 1.8M potatoes

我想在bash中将其转换为以下内容:

  1. 1300 apples
  2. 87900 oranges
  3. 156000 mangos
  4. 541700 carrots
  5. 1800000 potatoes

我使用的命令是将匹配的数字缩写字符串替换为完整的数字值,如下所示:

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

我的问题是,当发生变化时,我无法找到并替换所有可能的数字缩写。我想这样做,直到至少有一个十进制缩写。

wlwcrazw

wlwcrazw1#

鉴于:

  1. $ cat file
  2. 1.3K apples
  3. 87.9K oranges
  4. 156K mangos
  5. 541.7K carrots
  6. 1.8M potatoes

只是为了傻笑,纯粹的bash(sed和bc):

  1. while read -r x y
  2. do
  3. new_x=$(echo "$x" | sed -E 's/^([[:digit:].]*)[kK]/\1\*1000/; s/^([[:digit:].]*)[mM]/\1\*1000000/' | bc)
  4. printf "%'d %s\n" "$new_x" "$y"
  5. done <file

印刷品:

  1. 1,300 apples
  2. 87,900 oranges
  3. 156,000 mangos
  4. 541,700 carrots
  5. 1,800,000 potatoes
展开查看全部
p5cysglq

p5cysglq2#

这将执行全局替换(如果每行有>1个字符串要转换):

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

wqsoz72f3#

使用 numfmt 从GNUCoreutils,不要重新发明轮子。

  1. $ numfmt --from=si <file
  2. 1300 apples
  3. 87900 oranges
  4. 156000 mangos
  5. 541700 carrots
  6. 1800000 potatoes

如果缩写数字可能显示为任何字段,则可以使用:

  1. numfmt --from=si --field=- --invalid=ignore <file
nukf8bse

nukf8bse4#

另一个 awk 变体:

  1. awk '{q = substr($1, length($1));
  2. $1 *= (q == "M" ? 1000000 : (q=="K"?1000:1))} 1' file
  3. 1300 apples
  4. 87900 oranges
  5. 156000 mangos
  6. 541700 carrots
  7. 1800000 potatoes
pprl5pva

pprl5pva5#

以编程的方式,基于这个答案,您可以创建所有可能的转换因子的列表,并在需要时执行乘法:

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

x8diyxa76#

gnu awk for gensub():

  1. $ awk '
  2. BEGIN { mult[""]=1; mult["k"]=1000; mult["m"]=100000 }
  3. { $1 *= mult[gensub(/[^[:alpha:]]/,"","g",tolower($1))] }
  4. 1' file
  5. 1300 apples
  6. 87900 oranges
  7. 156000 mangos
  8. 541700 carrots
  9. 180000 potatoes
l2osamch

l2osamch7#

你能试着用gnu里的样品来写,测试一下吗 awk .

  1. awk '
  2. {
  3. if(sub(/[kK]$/,"",$1)){
  4. $1*=1000
  5. }
  6. if(sub(/[mM]$/,"",$1)){
  7. $1*=1000000
  8. }
  9. }
  10. 1
  11. ' Input_file

说明:增加了对以上内容的详细说明。

  1. awk ' ##Starting awk program from here.
  2. {
  3. 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.
  4. $1*=1000 ##Multiplying 1000 with current 1st field value here.
  5. }
  6. 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.
  7. $1*=1000000 ##Multiplying 1000000 with current 1st field value here.
  8. }
  9. }
  10. 1 ##1 will print current line here.
  11. ' Input_file ##Mentioning Input_file name here.

输出如下。

  1. 1300 apples
  2. 87900 oranges
  3. 156000 mangos
  4. 541700 carrots
  5. 1800000 potatoes
展开查看全部
kb5ga3dv

kb5ga3dv8#

这可能适用于您(gnu-sed):

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

创建查找并将其存储在保留空间中。
将查找附加到每行,并使用模式匹配将查找中的键替换为其值。
最后在没有找到匹配项时打印行。

e5nszbig

e5nszbig9#

另一种选择可能是仅使用bash和带有捕获组的模式,您可以在其中捕获任意一个组 M 或者 K . 如果模式匹配,则测试其中一个并设置乘数和使用 bc ```
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

  1. 输出

1300 apples
87900 oranges
156000 mangos
541700 carrots
1800000 potatoes

  1. bash演示
展开查看全部

相关问题