首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >bc算术误差

bc算术误差
EN

Unix & Linux用户
提问于 2018-10-29 10:43:58
回答 3查看 573关注 0票数 0

我按照这个指南来尝试并设置一个柠檬条配置:http://blog.z3bra.org/2014/04/meeting-at-the-bar.html

现在,除了这一行之外,几乎所有的事情都是完美无缺的:

代码语言:javascript
复制
bc <<< "scale=2; 100 - $f / $t * 100" | cut -d. -f1

在这项职能中:

代码语言:javascript
复制
memused() {
    read t f <<< `grep -E 'Mem(Total|Free)' /proc/meminfo |awk '{print $2}'`
    bc <<< "scale=2; 100 - $f / $t * 100" | cut -d. -f1
}

我得到以下错误(standard_in) 1: syntax error

现在,我可以告诉你,我应该在方程(())的周围加上两个括号,但是我尝试了大量不同的安排,但是没有什么能修正错误。

EN

回答 3

Unix & Linux用户

发布于 2018-10-29 10:58:33

awk可以在这里完成所有read's,cut's,grep‘和bc’的工作。

代码语言:javascript
复制
 awk -F': *' '
   $1 == "MemTotal" {t = $2}
   $1 == "MemFree" {f = $2}
   END {printf "%.1f%%\n", (t - f) * 100 / t}' /proc/meminfo

请注意,并非所有的awk实现都会输出40,5%,而不是40.5,在使用逗号作为十进制基数的地区(GNU awk只在POSIX模式下输出,就像$POSIXLY_CORRECT在环境中时那样)。使用LC_ALL=C awk...强制十进制基数为句点/点。

如果根本不需要十进制部分,则将%.1f更改为%.0f。它将舍入到最接近的整数。如果您想要截断小数部分,请使用%d (在99.999中获得99%而不是100% )。

假设read t f <<< `grep -E 'Mem(Total|Free)' /proc/meminfo |awk '{print $2}'`是未经修改的$IFS,那么您的D15在较早的bash版本中就能工作。

cmd <<< `code`中,bash用于将code的输出拆分到$IFS字符(默认情况下包括换行符),并将它们与$IFS的第一个字符(默认情况下为空格)连接,然后以stdin形式输入命令。因此,在你的例子中,awk的S输出的这两行最终将按照read t f的预期,在一行中作为两个单词来补充。这种令人惊讶的行为(也不同于zsh的最初实现)是在bash-4.4中修正的。

bash-4.4和更高版本中,您需要{ read t; read f; } <<< "$(awk...)" (这里在$(...)周围添加引号,这样它在bash-4.3和之前也能工作,仍然假定$IFS的默认值)。

票数 3
EN

Unix & Linux用户

发布于 2018-10-30 05:44:50

摘要:

便携式,一行,使用printf:

代码语言:javascript
复制
awk '/MemTotal/{t=$2}; /MemFree/{f=$2}; END{printf("%d\n",(1-f/t)*100)}'

只有Shell (bash):

代码语言:javascript
复制
memused() { : # Print the (integer) value of % of free memory
            local ret ref a t f 
            ret='MemTotal:[ \t]*([0-9]+)';              # Regex for Total memory.
            ref='MemFree:[ \t]*([0-9]+)';               # Regex for Free  memory.
            a=$(

描述

bc抱怨的原因是它只得到一个var。

复制:

代码语言:javascript
复制
$ t=150 ; f='' ; bc <<< "scale=2; 100 - $f / $t * 100"
(standard_in) 1: syntax error

避免此错误的一种方法是设置默认值:

代码语言:javascript
复制
$ t=150; f=''; bc <<< "scale=2; 100 - ${f:-0} / ${t:-0} * 100"
100

只有一个值的原因是读取是在单独的行中获取值(在bash4.4中)。一个适用于所有bash版本的解决方案是使用-d '':

代码语言:javascript
复制
$ read -d '' t f <<< "`grep -E 'Mem(Total|Free)' /proc/meminfo |awk '{print $2}'`"
$ echo "total=<$t>     free=<$f>"
total=<1922764>     free=<424360>

这也适用于命令扩展是否被引用(应该是"`grep … '`" )。

但我们没有理由称grep、awk、bc以及最终的cut。一次呼叫awk就可以做到这一切:

代码语言:javascript
复制

在一行中使用printf:

代码语言:javascript
复制
awk '/MemTotal/{t=$2};/MemFree/{f=$2};END{printf("%d\n",(1-f/t)*100)}' 

如果您希望更快地工作,并且只使用shell (尽管是bash):

代码语言:javascript
复制
memused() {  : # Print the (integer) value of % of free memory
             local ret ref a t f 
             ret='MemTotal:[ \t]*([0-9]+)';              # Regex for Total memory.
             ref='MemFree:[ \t]*([0-9]+)';               # Regex for Free  memory.
             a=$(
票数 1
EN

Unix & Linux用户

发布于 2018-10-29 10:58:56

read命令读取的字符串仅包含一个字段,其中2将同时填充tf变量。

您可以通过在| tr '\n' ' '命令之后添加awk来解决这个问题。

但最好将其简化为:

代码语言:javascript
复制
read t f <<< $(awk '/MemTotal/{t=$2}/MemFree/{f=$2}END{print t,f}' /proc/meminfo)
票数 0
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/478405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档