shell 命令输出中的字符数

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) 兼容。

cuo*_*glm 9

使用GNU expr

$ expr length + "$(readlink -f /etc/fstab)"
10
Run Code Online (Sandbox Code Playgroud)

+有GNU的一个特殊的功能expr,以确保下一个参数被视为一个字符串,即使它正好是一个expr像运营商matchlength+...

以上将删除输出的任何尾随换行符。要解决它:

$ 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。

  • `expr length $(echo "*")` — 不。至少使用双引号:`expr length "$(...)"`。但这会从命令中去除尾随换行符,这是命令替换的一个不可避免的特性。(你可以解决它,但答案会变得更加复杂。) (2认同)

ter*_*don 6

不确定如何使用 shell 内置函数(虽然是 Gnouc)来做到这一点,但标准工具可以提供帮助:

  1. 您可以使用wc -mwhich 计数字符。不幸的是,它还计算了最后的换行符,因此您必须首先摆脱它:

    readlink -f /etc/fstab | tr -d '\n' | wc -m
    
    Run Code Online (Sandbox Code Playgroud)
  2. 你当然可以使用 awk

    readlink -f /etc/fstab | awk '{print length($0)}'
    
    Run Code Online (Sandbox Code Playgroud)
  3. 或 Perl

    readlink -f /etc/fstab | perl -lne 'print length'
    
    Run Code Online (Sandbox Code Playgroud)


slm*_*slm 5

我通常这样做:

$ 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 个步骤中所做的,除了我们将它们组合成一个单一的衬垫。

  • 您必须使用 `-m` 而不是 `-c`。使用 unicode 字符,您的方法将被破坏。 (2认同)