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

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

例如,如果我有以下文本文件:

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

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

1300 apples
87900 oranges
156000 mangos
541700 carrots
1800000 potatoes
1300 apples
87900 oranges
156000 mangos
541700 carrots
1800000 potatoes
1300 apples
87900 oranges
156000 mangos
541700 carrots
1800000 potatoes

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

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

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

回答

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

$ numfmt --from=si <file
1300 apples
87900 oranges
156000 mangos
541700 carrots
1800000 potatoes

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

numfmt --from=si --field=- --invalid=ignore <file


回答

您能否尝试使用 GNU 中显示的示例进行跟踪、编写和测试awk

awk '
{
  if(sub(/[kK]$/,"",$1)){
    $1*=1000
  }
  if(sub(/[mM]$/,"",$1)){
    $1*=1000000
  }
}
1
' Input_file

说明:为以上添加详细说明。

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.

输出如下。


回答

另一种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


回答

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

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


回答

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

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


回答

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

输出

Bash 演示


回答

使用用于 gensub() 的 GNU awk:

$ 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


回答

鉴于:

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

只是为了傻笑,纯 Bash(带有 sed 和 bc):

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

印刷:

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


回答

这可能对你有用(GNU sed):

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

创建查找并将其存储在保留空间中。

将查找附加到每一行并使用模式匹配将查找中的键替换为其值。

最后在找不到更多匹配项时打印该行。


以上是将所有数字缩写转换为文本文件中的数值的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>