Вы не можете включить ]
в класс символов путем обратного слэширования. Он должен быть первым элементом в классе. То же самое относится и к тире, но на этот раз оно должно быть последним. \-\^
просто соответствует диапазону от \
до \
, т.е. обратной косой черты и каретки. (Я также удалил бесполезные обратные слеши).
regex='^[]0-9a-zA-Z,!^`@{}=().;/~_|[-]*$'
Вы уверены, что вам нужно *
, а не +
? Вы действительно хотите принимать пустые строки?
Если вы ищете zsh
встроенную альтернативу этому не -стандартному expr
использованию (, ничего общего с bash
между прочим ), вы можете:
$ a=abcdefghijklmnopqrstuvwxyz b=xyzd
$ echo ${a[(i)[$b]]}
4
С помощью i
вы получаете индекс первого совпадения (или единицу плюс длину стога сена, если совпадения нет ). Вместо этого с I
вы получите последнее совпадение (или 0, если совпадения нет ).
С любой оболочкой, подобной POSIX -(, включая bash
иzsh
)
$ s=${a%%[$b]*}
$ echo "$(($#s + 1))"
4
Реализация expr
, найденная в пакете GNU coreutils, является внешней утилитой и может использоваться одинаково независимо от того, какую оболочку вы используете.
В zsh
,
expr index "abcdefghijklmnopqrstuvwxyz" xyzd
вернет 4
, как в bash
или любой другой оболочке.
Операция index
в GNU expr
является расширением стандарта expr
, что означает, что вы, скорее всего, получите ошибку expr: syntax error
в системах без этой конкретной реализации expr
. Это независимо от того, какую оболочку вы используете.
Как уже указал Кусалананда в своем комментарии, вы, конечно, можете использовать expr
и в zsh, но я думаю, вы имели в виду, есть ли в Zsh встроенный способ сделать это.
Ответ "нет", но в нем есть что-то похожее:
v="abcdefghijklmnopqrstuvwxyz"
i=${(SB)v#cdef}
Это установит i
на 3. Однако есть две причины, по которым это не работает точно так же, какexpr index
:
В приведенном вами примере вы ищете xyzd , которого нет в вашей строке, но поскольку ваша строка заканчивается на xyz , expr
изящно удаляет ' 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
ОБНОВЛЕНИЕ :Как показывают комментарии к этому сообщению, я неправильно понял цель expr index
; следовательно, мой ответ в том виде, в каком он дан, неадекватен. Однако мы можем адаптировать его, потому что искомая "строка" представляет собой шаблон глобуса -. Следовательно, квадратные скобки сделают эту работу :
# Search for the first occurance of one of the letters x y z d
index_and_length=${(SBN)v#[xyzd]}