我正在按照本指南尝试设置柠檬吧配置:http://blog.z3bra.org/2014/04/meeting-at-the-bar.html
现在,除了这一行之外,几乎所有内容都可以完美运行:
bc <<< "scale=2; 100 - $f / $t * 100" | cut -d. -f1
在这个函数中:
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
现在据我所知,我应该在方程周围添加双括号,(())
但我尝试了很多不同的安排,但没有任何方法可以修复错误。
答案1
awk
可以在这里完成所有read
's、cut
's、grep
's 和bc
's 工作:
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(GNUawk
仅在 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}'`
将在bash
假设未修改的旧版本中工作$IFS
。
在 中cmd <<< `code`
,用于分割on 个字符(默认情况下包括换行符)的bash
输出,并在作为标准输入输入命令之前将它们与第一个字符(默认情况下为空格)连接起来。因此,在您的情况下,的输出的这两行最终将按照 的预期作为一行上的两个单词提供。这种令人惊讶的行为(也与 中的原始实现不同)在 bash-4.4 中得到了修复。code
$IFS
$IFS
awk
read t f
zsh
在上面bash-4.4
和上面,你需要{ read t; read f; } <<< "$(awk...)"
(这里添加引号,$(...)
这样它也可以在 bash-4.3 及之前的版本中工作,仍然假设默认值$IFS
)。
答案2
抽象的:
便携式,一行并使用 printf:
awk '/MemTotal/{t=$2}; /MemFree/{f=$2}; END{printf("%d\n",(1-f/t)*100)}'
仅外壳(bash):
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=$(</proc/meminfo) # Get meminfo in var (a).
[[ $a =~ $ret ]] && t="${BASH_REMATCH[1]}" # Get Total memory.
[[ $a =~ $ref ]] && f="${BASH_REMATCH[1]}" # Get Free memory.
printf '%s\n' "$(( 100 - 100*f/t )) %" # Print integer % value.
}
描述
BC 抱怨的原因是它只得到一个 var。
重现:
$ t=150 ; f='' ; bc <<< "scale=2; 100 - $f / $t * 100"
(standard_in) 1: syntax error
避免该错误的一种方法是设置默认值:
$ t=150; f=''; bc <<< "scale=2; 100 - ${f:-0} / ${t:-0} * 100"
100
只有一个值的原因是读取是在单独的行中获取值(在 bash 4.4 中)。适用于所有 bash 版本的解决方案是使用-d ''
:
$ 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
。一次调用 awk 即可完成这一切:bc
cut
</proc/meminfo awk '/MemTotal/{t=$2}
/MemFree/ {f=$2}
END{
print( (1-f/t)*100 )
}
'
在一行中并使用 printf:
awk '/MemTotal/{t=$2};/MemFree/{f=$2};END{printf("%d\n",(1-f/t)*100)}' </proc/meminfo
如果你想要运行得更快并且只使用 shell(尽管是 bash):
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=$(</proc/meminfo) # Get meminfo in var (a).
[[ $a =~ $ret ]] && t="${BASH_REMATCH[1]}" # Get Total memory.
[[ $a =~ $ref ]] && f="${BASH_REMATCH[1]}" # Get Free memory.
printf '%s\n' "$(( 100 - 100*f/t )) %" # Print integer % value.
}
答案3
命令读取的字符串read
仅包含 1 个字段,其中 2 个字段预计同时填充t
和f
变量。
可以通过在命令| tr '\n' ' '
后面添加来解决awk
。
但最好将其简化为:
read t f <<< $(awk '/MemTotal/{t=$2}/MemFree/{f=$2}END{print t,f}' /proc/meminfo)