从 Zsh 中的字符串末尾修剪空格

Trimming whitespace from the ends of a string in Zsh

如何在不产生另一个进程的情况下从 Zsh 中的字符串末尾删除任何和所有白色space?

查看 the documentation for expansion in Zsh (namely sections 14.3 Parameter Expansion and 14.8.1 Glob Operators) 之后——也可以通过 $ man zshexpn 查看——我编写了以下代码:

${${var##[:space:]##}%%[:space:]##}

但 Zsh 似乎无法识别 [:space:] glob 运算符。根据我对文档中以下语句的理解,它 should:

In the expansions discussed below that require a pattern, the form of the pattern is the same as that used for filename generation; see Filename Generation. Note that these patterns, along with the replacement text of any substitutions, are themselves subject to parameter expansion, command substitution, and arithmetic expansion.

这是 Zsh 中的错误还是我忽略了什么?

目前,我只使用 ${${var## ##}%% ##},它至少替换了末尾的所有 space 个字符。

我正在使用 Zsh 5.8。

引用 zsh Glob Operator 文档:

Note that the square brackets are additional to those enclosing the whole set of characters, so to test for a single alphanumeric character you need ‘[[:alnum:]]’.

所以只使用 [:space:] 而不是 [[:space:]] 是你的问题。


旁白:

zsh glob 模式中,有几种方式可以表示“匹配先前事物的多个副本”。您使用的一种方法需要打开 EXTENDED_GLOB 选项,即使用 x##,它 匹配模式 x 的一次或多次出现(有也 x#,它 匹配零次或多次出现的模式 x)。另一个需要 KSH_GLOB 选项才能工作的是 +(x),它也匹配一次或多次出现的 x(而 *(x) 匹配 0 次或多次。)这种风格有使用 kshbash 的优势(后者需要启用 extglob 选项)因此对于来自另一个 shell.[=28= 的人来说可能更熟悉]

所以:

$ foo=$(printf " \t bar baz \t ") # Spaces and tabs before and after
$ printf ">%s<\n" "$foo"                               
>    bar baz     <
$ printf ">%s<\n" "${${foo##[[:space:]]##}%%[[:space:]]##}"
>bar baz<
$ setopt KSH_GLOB                                            
$ printf ">%s<\n" "${${foo##+([[:space:]])}%%+([[:space:]])}"
>bar baz<

根据需要删除所有前导和尾随空白字符。

另请注意,这种扩展嵌套是 zsh 特定的。它在其他 shell 中不起作用,其中两个删除将需要多个步骤。

你真的很接近。

  1. 您需要稍微修改一下 POSIX Basic Regular Expression 字符 class 语法
  2. 您可以使用 (MS)(匹配子字符串)parameter expansion flags.
  3. 来简化表达式
${(MS)var##[[:graph:]]*[[:graph:]]}

解决方案

在下面的示例中,我们将从中删除 leading/trailing 空格的参数具有标识符 var。根据需要在您自己的代码中替换它。

typeset var=$'\n\t   abc   def   \n\t'

打印去除任何 leading/trailing 空格的参数:

print -n -- ${(MS)var##[[:graph:]]*[[:graph:]]}

输出abc def

$ foo=" \n \t  ab dd ef   \n"

$ print $foo | xargs
ab dd ef