regex - 测量单位正则表达式操作

标签 regex perl awk

客观的

Linux ,我试图获得一个代表可用系统内存的最终用户友好字符串。

例子:

Your computer has 4 GB of memory.

成功标准

我认为这些方面对最终用户友好(您可能不同意):
  • 1G1.0G 更具可读性( 11.0 )
  • 1GB1G 更具可读性( GBG )
  • 1 GB1GB 更具可读性( space-separated 计量单位)
  • memoryRAM 更具可读性, DDRDDR3 (无行话)

  • 初始点

    free 实用程序来自 procps-ng 有一个供人类使用的选项:

    -h, --human
        Show all output fields automatically scaled to shortest three digit unit
        and display the units of print out.  Following units are used.
            B = bytes
            K = kilos
            M = megas
            G = gigas
            T = teras
        If unit is missing, and you have petabyte of RAM or swap, the number is
        in terabytes and columns might not be aligned with header.
    

    所以我决定从那里开始:

    > free -h
                 total       used       free     shared    buffers     cached
    Mem:          3.8G       1.4G       2.4G         0B       159M       841M
    -/+ buffers/cache:       472M       3.4G
    Swap:         4.9G         0B       3.9G
    
    3.8G听起来很有希望,所以我现在要做的就是......

    所需步骤
  • 过滤包含人类可读字符串的行的输出(即 Mem: )
  • 从行的中间挑出内存总量(即 3.8G )
  • 解析出数字和度量单位(即 3.8G )
  • 根据我的喜好格式化和显示字符串(例如 GGB , ...)

  • 我的尝试

    free -h | \
      awk  '/^Mem:/{print $2}' | \
        perl -ne '/(\d+(?:\.\d+)?)(B|K|M|G|T)/ && printf "%g %sB\n", $1, $2'
    

    输出:

    3.8 GB
    

    所需的解决方案
  • 我宁愿只使用 gawk ,但我不知道如何
  • 如果有的话,使用更好的,甚至规范的方法来解析字符串中的“浮点数”
  • 我不介意“只是公认的大小字母”的挑剔匹配(B|K|M|G|T) ,即使这会因引入新尺寸而不必要地破坏匹配
  • 我用 %g输出 4.04 ,这可能是您不同意的,具体取决于您对这些评论的看法:https://unix.stackexchange.com/a/70553/10283 .

  • 我的问题,总结
  • 你能在awk中做以上的事情吗?只要?
  • 请问我的perl写得比那更优雅,保持它的严格性?

  • 记住:

    I am a beginner robot. Here to learn. :]
    

    我从安迪莱斯特那里学到了什么

    为了我自己的利益,在这里总结一下:如果可以的话,巩固学习。
  • 使用 regex character classes ,不是 regex alternation , 从集合中挑选一个字符
  • perl 有一个 -a选项,它拆分 $_来自 -e-n进入 @F :

  • 例如,这个 gawk :

    echo foo bar baz | awk '{print $2}'
    

    可以这样写在 perl :

    echo foo bar baz | perl -ane 'print "$F[1]\n";'
    

    除非有等同于 的东西gawk --field-separator ,我想我还是喜欢 gawk 更好,虽然当然要在 中做所有事情perl 更清洁,更高效。 (有等价物吗?)

    编辑 : 实际上,这证明存在,而且是-F就像在 gawk :
    echo ooxoooxoooo | perl -Fx -ane 'print join "\n", @F'
    

    输出:
    oo
    ooo
    oooo
    

  • perl 有一个 -l选项,这真是太棒了:把它想象成 Python str.rstrip (如果您不是 Python 头像,请查看链接)了解 $_ 的有效性但它重新附加了 \n自动为您输出

  • 谢谢,安迪!

    最佳答案

    是的,我相信你可以只用 awk 来做这个,但我是一个 Perl 人,所以这里是你如何只用 Perl 来做的。

    而不是 (B|K|M|G|T)使用 [BKMGT] .

    使用 Perl 的 -l自动从输入中去除换行符并将它们添加到输出中。

    我看不出有任何理由让 Awk 做一些剥离工作,而让 Perl 做其余的工作。您可以使用 Perl 的 -a 自动拆分字段。

    我不知道 free -h 的输出是什么正是(我的 free 没有 -h 选项)所以我猜这个

    free -h | \
    perl -alne'/^Mem:/ && ($F[1]=~/(\d+(?:\.\d+)?)[BKMGT]/) && printf( "%g %sB", $1, $2)'
    

    关于regex - 测量单位正则表达式操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15713649/

    相关文章:

    perl - 循环遍历数组以使用 Perl 比较两个值

    awk - 使用 awk 将字段分隔符 ',' 更改为空格

    javascript正则表达式删除额外的p标签

    regex - 带有正则表达式的字符串之间的 Grep 值

    linux - 在 Linux 上安装 Crypt::SSLeay 时出错

    regex - ?+* 在正则表达式中没有任何内容

    bash - 如何使用 bash 在两个已知行 block 之间的文件中插入一行(如果之前尚未插入)?

    bash - awk:在读取行之前打印文件的第一行

    REGEX:如果 KeyWord2 在同一个字符串中,则选择 KeyWord1

    python - re.scanner 只搜索字符串的开头