Zsh 相当于 bash 的 `expr 索引 "abcdefghijklmnopqrstuvwxyz" xyzd`

Zsh 相当于 bash 的 `expr 索引 "abcdefghijklmnopqrstuvwxyz" xyzd`

Zsh 相当于 bash 的什么

expr index "abcdefghijklmnopqrstuvwxyz" xyzd

我正在尝试查找子字符串的索引。

答案1

如果您正在寻找zsh非标准expr用法的内置替代方案(与顺便说一句无关bash),您可以这样做:

$ a=abcdefghijklmnopqrstuvwxyz b=xyzd
$ echo ${a[(i)[$b]]}
4

使用i,您可以获得的索引第一的匹配(如果没有匹配,则加上干草堆的长度)。相反I,您将获得最后一个匹配项(如果没有匹配项,则为 0)。

使用任何类似 POSIX 的 shell(包括bashzsh

$ s=${a%%[$b]*}
$ echo "$(($#s + 1))"
4

答案2

GNU coreutils 包中的实现expr是一个外部实用程序,无论您使用什么 shell,都可以以相同的方式使用。

zsh

expr index "abcdefghijklmnopqrstuvwxyz" xyzd

将返回4,就像在 shellbash或任何其他 shell 中一样。

indexGNU 中的操作是expr标准expr,这意味着您可能会在expr: syntax error没有特定实现的系统上遇到错误expr。这与您使用什么 shell 无关。

答案3

expr index "abcdefghijklmnopqrstuvwxyz" xyzd

我正在尝试查找子字符串的索引。

子字符串的索引,还是字符的索引?expr index查找第二组中给出的任何字符,即上面查找第一个字符的位置d,而不是子字符串xyzd(字符串中不存在)。

要查找子字符串的位置,您可以在标准 shell 中执行以下操作:

haystack=abcdefghijklmnopqrstuvwxyz
needle=jkl
x=${haystack%%$needle*};

现在x包含该子字符串之前的字符串部分,( ,在本例中)"${#x}"的从零开始的位置也是如此。jkl9

要从一组字符中查找字符(字节)的位置,您可以类似地使用:

haystack=abcdefghijklmnopqrstuvwxyz
needle=xqe;
x=${haystack%%[$needle]*}; 

这里,"${#x}"是 4。这两种方法的缺点是,如果未找到所搜索的字符串/字符,则x包含整个haystack,因此您需要"${#x}"与整个长度haystack(非零)进行比较以查看是否找到匹配项:

haystack=abcdefghijklmnopqrstuvwxyz
needle=qqq
x=${haystack%%$needle*}
if [ "${#x}" = "${#haystack}" ]; then echo "$needle not found"; fi

答案4

正如 Kusalananda 在他的评论中已经指出的那样,你当然expr也可以在 zsh 中使用,但我猜你的意思是 Zsh 是否有内置方法来做到这一点。

答案是“不”,但它包含类似的内容:

v="abcdefghijklmnopqrstuvwxyz"
i=${(SB)v#cdef}

这将设置i为 3。但是,有两个原因导致其工作方式与expr index

在您给出的示例中,您正在搜索XYZD,它不存在于您的字符串中,但由于您的字符串以XYZexpr优雅地删除“d”并返回匹配项。有人可能会说 Zsh 的行为在这方面更合理,但当然,如果这对你来说是一个重要问题,我会坚持使用 Zsh。

Zsh 不同的另一个原因是,${(SB)v#...}如果字符串不存在,则返回 1不是匹配。例如,

echo ${(SB)v#a}
echo ${(SB)v#7}

都会返回 1。仅凭这一点,您无法区分第一个字符的不匹配和匹配。一种可能的解决方案是让它计算比赛的位置和长度:

# N returns the length of the match
index_and_length=${(SBN)v#...}
# index_and_length contains the index, a space, and the length
if [[ ${index_and_length#* } == 0 ]]
then
  echo no match
else
  index=${index_and_length% *}
  echo match at index $index
fi

UDPATE:正如这篇文章的评论所揭示的那样,我误解了expr index;因此,我的回答是不充分的。但是我们可以调整它,因为要搜索的“字符串”是一个全局模式。因此,方括号可以完成这项工作:

# Search for the first occurance of one of the letters x y z d
index_and_length=${(SBN)v#[xyzd]}

相关内容