use*_*676 13 shell string variable
我正在编写一个脚本,它需要一步计算命令输出中的字符数。
例如,使用该命令readlink -f /etc/fstab应该返回,10因为该命令的输出长度为 10 个字符。
这已经可以使用以下代码存储变量:
variable="somestring";
echo ${#variable};
# 10
Run Code Online (Sandbox Code Playgroud)
不幸的是,对命令生成的字符串使用相同的公式不起作用:
${#(readlink -f /etc/fstab)};
# bash: ${#(readlink -f /etc/fstab)}: bad substitution
Run Code Online (Sandbox Code Playgroud)
我知道可以通过首先将输出保存到变量来做到这一点:
variable=$(readlink -f /etc/fstab);
echo ${#variable};
Run Code Online (Sandbox Code Playgroud)
但我想删除额外的步骤。
这可能吗?最好仅使用内置或标准实用程序与 Almquist shell (sh) 兼容。
使用GNU expr:
$ expr length + "$(readlink -f /etc/fstab)"
10
Run Code Online (Sandbox Code Playgroud)
在+有GNU的一个特殊的功能expr,以确保下一个参数被视为一个字符串,即使它正好是一个expr像运营商match,length,+...
以上将删除输出的任何尾随换行符。要解决它:
$ expr length + "$(readlink -f /etc/fstab; printf .)" - 2
10
Run Code Online (Sandbox Code Playgroud)
结果被减为2,因为最后的换行符readlink和.我们添加的字符。
使用 Unicode 字符串,expr似乎不起作用,因为它返回以字节为单位的字符串长度而不是字符数(参见第 654 行)
$ LC_ALL=C.UTF-8 expr length ?aa
4
Run Code Online (Sandbox Code Playgroud)
因此,您可以使用:
$ printf "?aa" | LC_ALL=C.UTF-8 wc -m
3
Run Code Online (Sandbox Code Playgroud)
POSIXLY:
$ expr " $(readlink -f /etc/fstab; printf .)" : ".*" - 3
10
Run Code Online (Sandbox Code Playgroud)
命令替换前的空格防止命令以字符串开头崩溃-,因此我们需要减去 3。
不确定如何使用 shell 内置函数(虽然是 Gnouc)来做到这一点,但标准工具可以提供帮助:
您可以使用wc -mwhich 计数字符。不幸的是,它还计算了最后的换行符,因此您必须首先摆脱它:
readlink -f /etc/fstab | tr -d '\n' | wc -m
Run Code Online (Sandbox Code Playgroud)你当然可以使用 awk
readlink -f /etc/fstab | awk '{print length($0)}'
Run Code Online (Sandbox Code Playgroud)或 Perl
readlink -f /etc/fstab | perl -lne 'print length'
Run Code Online (Sandbox Code Playgroud)我通常这样做:
$ echo -n "$variable" | wc -m
10
Run Code Online (Sandbox Code Playgroud)
要执行命令,我会像这样调整它:
$ echo -n "$(readlink -f /etc/fstab)" | wc -m
10
Run Code Online (Sandbox Code Playgroud)
这种方法类似于您在 2 个步骤中所做的,除了我们将它们组合成一个单一的衬垫。