Zsh equivalente do 'expr index' de bash abcdefghijklmnopqrstuvwxyz ”xyzd '

1

Qual seria o equivalente do Zsh do bash

expr index "abcdefghijklmnopqrstuvwxyz" xyzd

Estou tentando encontrar o índice de substring.

    
por fg78nc 31.07.2018 / 04:54

4 respostas

2

Se você está procurando uma alternativa zsh incorporada a esse uso não padrão de expr (nada a ver com bash btw), você poderia fazer:

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

Com i , você obtém o índice da primeira correspondência (ou uma mais a extensão do palheiro se não houver correspondência). Com I , você recebe a última correspondência (ou 0 se não houver correspondência).

Com qualquer shell parecido com POSIX (incluindo bash e zsh )

$ s=${a%%[$b]*}
$ echo "$(($#s + 1))"
4
    
por 31.07.2018 / 09:59
3

A implementação do expr encontrado no pacote GNU coreutils é um utilitário externo e pode ser usado da mesma maneira, independentemente do shell que você está usando.

Em zsh ,

expr index "abcdefghijklmnopqrstuvwxyz" xyzd

retornaria 4 , assim como em bash ou qualquer outro shell.

A operação index no expr do GNU é uma extensão do padrão expr , o que significa que você provavelmente obterá um erro expr: syntax error nos sistemas sem essa implementação específica de expr . Isso é independente do shell que você usa.

    
por 31.07.2018 / 07:45
2

expr index "abcdefghijklmnopqrstuvwxyz" xyzd

I am trying to find index of substring.

Índice de uma substring ou de um caractere? expr index procura qualquer um dos caracteres fornecidos no segundo conjunto, ou seja, o acima encontra a posição do primeiro d , não a subcadeia xyzd (que não existe na sua cadeia).

Para procurar a posição de uma substring, você poderia fazer no shell padrão:

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

Agora, x contém a parte da string antes dessa subseqüência, então "${#x}" é a posição baseada em zero de jkl ( 9 , nesse caso).

Para procurar a posição de um caractere (byte) de um conjunto de caracteres, você também pode usar:

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

Aqui, "${#x}" é 4. A desvantagem de ambos é que se a string / caractere sendo pesquisado não for encontrada, x contém o total de haystack , então você precisa comparar "${#x}" em relação ao comprimento total de haystack (não zero) para ver se uma correspondência foi encontrada:

haystack=abcdefghijklmnopqrstuvwxyz
needle=qqq
x=${haystack%%$needle*}
if [ "${#x}" = "${#haystack}" ]; then echo "$needle not found"; fi
    
por 31.07.2018 / 10:14
0

Como Kusalananda já apontou em seu comentário, é claro que você pode usar expr em zsh, mas eu acho que você quis dizer se o Zsh tem uma maneira integrada para fazê-lo.

A resposta é "não", mas contém algo semelhante:

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

Isso definiria i como 3. No entanto, há dois motivos pelos quais isso não funciona exatamente como expr index :

No exemplo que você deu, você está procurando por xyzd , que não está presente em sua string, mas como sua string termina em xyz , expr normalmente cai o 'd' e retorna uma correspondência. Pode-se argumentar que o comportamento de Zsh é mais razoável a este respeito, mas é claro que se isso é uma questão importante para você, eu ficaria com Zsh.

A outra razão pela qual o Zsh é diferente, é que ${(SB)v#...} retorna 1 se a string não corresponde. Por exemplo,

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

os dois retornariam 1. Com isso sozinho, você não pode distinguir entre um não-jogo e uma correspondência no primeiro caractere. Uma solução possível é calcular a posição e a duração da partida:

# 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: Como os comentários deste post revelam, não entendi o propósito de expr index ; portanto, minha resposta, como dada, é inadequada. No entanto, podemos adaptá-lo, porque a "string" a ser pesquisada é um padrão glob. Assim, colchetes fará o trabalho:

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

Tags