【问题标题】:Rounding numerical values with trailing 9s用尾随 9 舍入数值
【发布时间】:2015-07-16 15:25:37
【问题描述】:

我正在尝试在数字字符串中查找最大值,并且某些数据包含尾随 9。

999999999999 63 66 69 71 73 75 76 78 80 81 81 80 79 74 67 63999999999999999

我一直在使用以下命令来查找数字的最大值,但显然该命令将带有尾随 9 的数据视为“最大值”(例如,6399999 ....)并忽略实际最大值价值观。部分数据还包含一堆 9 的不良数据。

grep -Eo '[0-9]+' file_temp | sort -rn | head -n 1 > file_temp_max

如何去除不良数据(例如 999999)以及如何更正带有尾随 9 的值(6399999...> 64),以便可以将它们四舍五入(并包含在数据集中) ?

【问题讨论】:

  • 999999999999 变成了什么?
  • 是的,任何带有“999999999999999”的数字都应该四舍五入,并且应该删除“999999999999”。
  • 那么9个数据好不好? 99? 999呢?

标签: regex linux bash unix numeric


【解决方案1】:

这与 Adams 的回答略有不同,它在循环中使用 sed。

首先,我假设您不知道将包含多少个 9。其次,我正在使用中间转换来浮动。

for line in $(cat file_temp); do 
    i=$(echo $line |  sed 's/../.&/;t;s/^.$/.0&/');
    printf "%.02f\n" $i;
done | sed 's/\.//;s/^0//' | sort -nr

细分:

sed 's/../.&/;t;s/^.$/.0&/'第二个字符后加一个小数点

printf "%.02f\n" $i; 将值打印为浮点数 - 自动为您四舍五入。

sed 's/\.//;s/^0//' 去除前导 0 和 .只留下剩余的整数

【讨论】:

  • 您可能会溢出行缓冲区,将file_temp 的全部内容放到命令行中。您还对每个数字的大小进行了假设。我的代码假定 1239999999999999999 是 1240,而这假定它是 12。
  • 您可以通过将第一行更改为grep -Eo '[0-9]+' | while read line; do来解决缓冲区问题
  • for x in $(cat file) 将遍历文件中的单词,除非IFS=$'\n' -- 你想要while IFS= read -r line; do ...; done < file_temp
【解决方案2】:

要“清理”数据,您可以通过遍历所有字段来执行以下操作:

  • 如果它仅包含在 9s 中,请将其删除。
  • 如果它以多个 9s 结尾,请将它们删除并将剩余的数字加一。

根据您给定的输入查看它的实际效果:

$ awk '{for(i=1;i<=NF;i++) {if ($i~/^9+$/) $i=""; if (sub(/9+$/,"",$i)) $i++}}1' a 
 63 66 7 71 73 75 76 78 80 81 81 80 8 74 67 64

然后通过使用How to get the biggest number in a file? 中的任何算法来获得最大值是微不足道的

【讨论】:

    【解决方案3】:

    你可以使用这个 awk:

    awk -v RS=' ' '{gsub(/9+$/, ".&", $1); $1=int($1); print $1; if ($1>max) max=$1}
                    END{print "max = ", max}' file
    0
    63
    66
    6
    71
    73
    75
    76
    78
    80
    81
    81
    80
    7
    74
    67
    64
    max =  81
    

    gsub(/9+$/, ".&amp;", $1) 会在 9 结束前插入一个小数点。

    $1=int($1) 将从十进制数中获取整数值,从而将它们四舍五入。

    if ($1&gt;max) max=$1 是简单的max 计算。

    【讨论】:

      【解决方案4】:

      我假设“一个空格后跟 2 位数字”是提取所需数字的有效方法:

      echo 999999999999 63 66 69 71 73 75 76 78 80 81 81 80 79 74 67 63999999999999999 | 
      grep -o ' [0-9][0-9]' | 
      sort -n | 
      tail -1
      

      生产

       81
      

      【讨论】:

        【解决方案5】:

        从您的示例代码构建:

        grep -Eo '[0-9]+' file_temp | awk '
          $1 ~ /999999999999999/ { sub(/999999999999999$/,""); $1++}
          $0 != 999999999999'
        

        这会在自己的行中获取每个数字,然后使用awk 修改每一行。 awk 检查任何有 15 个 9s 的行并将它们剥离,然后增加数字。下一行打印任何不是 11 个 9 的内容。

        以上假设1239999999999999999 应该是1240。如果相反,它应该是124:

        grep -Eo '[0-9]+' file_temp | awk '
          $1 ~ /^999+$/ { next }
          $1 ~ /999$/ { sub(/9+$/,""); $1++}
          { print }'
        

        第一行awk 跳过只有九的行,第二行删除所有尾随行并增加数字,第三行打印。假设999 是有效的,我正在键入3+ 9。

        【讨论】:

          猜你喜欢
          • 2021-12-09
          • 1970-01-01
          • 2021-05-24
          • 1970-01-01
          • 2014-09-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多