$ * da função zsh leva a resultados inesperados

1

Eu tenho essa função (definida dentro do meu ~ / .zshrc):

function graliases
{
    if [[ "$#*" -lt 1 ]]
    then
        echo "Usage: graliases <regex>"
    else
        echo "$*"
        grep -E '*"$*"*' ~/.dotfiles/zsh/aliases.zsh
    fi
}

O que esta função deve fazer, é procurar o arquivo ~/.dotfiles/zsh/aliases.zsh com um regex, fornecido pelos parâmetros. Para o regex, duas estrelas são anexadas e prefixadas, o que deve tornar a descoberta independente da posição na linha. Minha ideia funciona, se eu usar grep simples:

$ grep -E '*git rebase*' ~/.dotfiles/zsh/aliases.zsh
    alias gr='git rebase'
    alias gra='git rebase --abort'
    alias grc='git rebase --continue'
    alias gri='git rebase --interactive'
    alias grs='git rebase --skip'


$ grep -E '*ls -la*' ~/.dotfiles/zsh/aliases.zsh
alias lnew='ls -ld *(/om[1,3])'     # Show three newest directories. "om" orders by modification. "[1,3]" works like Python slice.
alias lsize='ls -l */**(Lk+100)'    # List all files larger than 100kb in this tree
alias lvd='ls -ld **/*(/^F)'        # recursively list any empty sub-directories
alias l='ls -lph'                   # size,show type,human readable
alias la='ls -lAph'                 # long list,show almost all,show type,human readable
alias lt='ls -lAtph'                # long list,sorted by date,show type,human readable

O recuo neste exemplo grep é como deveria ser, isso não é um erro. Minha função deve basicamente fazer o mesmo, apenas com o conteúdo entre as duas estrelas como parâmetros (nesse caso, git rebase e ls -la .

Mas não faz o mesmo e não sei porque:

$ graliases git branch
git branch
alias lnew='ls -ld *(/om[1,3])'     # Show three newest directories. "om" orders by modification. "[1,3]" works like Python slice.
    alias findAllIPs="nmap -sP 192.168.1.* | grep -oE '192.168.1.[0-9]*'"
    alias findLocalIP="ifconfig | grep -oE 'inet 192.168.1.[0-9]*'"
    alias apls="apt list"
    alias gcR='git reset "HEAD^"'
    alias gdi='git status --porcelain --short --ignored | sed -n "s/^!! //p"'
    alias ggf="git ls-files | grep -i"
    alias gCl='git status | sed -n "s/^.*both [a-z]*ed: *//p"'
    alias gpc='git push --set-upstream origin "$(git-branch-current 2> /dev/null)"'
    alias gpp='git pull origin "$(git-branch-current 2> /dev/null)" 
          && git push origin "$(git-branch-current 2> /dev/null)"'
    alias gwig="git update-index --assume-unchanged"
    alias gwuig="git update-index --no-assume-unchanged"



% graliases ls -la
ls -la
alias lnew='ls -ld *(/om[1,3])'     # Show three newest directories. "om" orders by modification. "[1,3]" works like Python slice.
    alias findAllIPs="nmap -sP 192.168.1.* | grep -oE '192.168.1.[0-9]*'"
    alias findLocalIP="ifconfig | grep -oE 'inet 192.168.1.[0-9]*'"
    alias apls="apt list"
    alias gcR='git reset "HEAD^"'
    alias gdi='git status --porcelain --short --ignored | sed -n "s/^!! //p"'
    alias ggf="git ls-files | grep -i"
    alias gCl='git status | sed -n "s/^.*both [a-z]*ed: *//p"'
    alias gpc='git push --set-upstream origin "$(git-branch-current 2> /dev/null)"'
    alias gpp='git pull origin "$(git-branch-current 2> /dev/null)" 
          && git push origin "$(git-branch-current 2> /dev/null)"'
    alias gwig="git update-index --assume-unchanged"
    alias gwuig="git update-index --no-assume-unchanged"

De acordo com 1 , 2 , $* é a variável correta para este caso de uso. Até mesmo a linha echo "$*" imprime o resultado esperado. Infelizmente, ainda não encontrei uma explicação explícita de $* na página do zsh.

Por que minha função não funciona corretamente?

    
por toogley 26.06.2016 / 13:36

1 resposta

3

O padrão grep parece errado. A regra geral da linha de comando é que tudo dentro de aspas simples é tomado literalmente, enquanto que quando não citadas ou dentro de aspas duplas, o shell expande essa string de acordo com suas regras (globing, splitting, expansão de parâmetro etc.). No seu caso, o comando

grep -E '*"$*"*' ~/.dotfiles/zsh/aliases.zsh

significa passar para grep string *"$*"* literalmente, para que grep interprete este padrão como estrela, seguido por aspas duplas, seguido por sinal dolar repetido zero ou mais vezes ( * ), seguido por aspas duplas repetido zero ou mais vezes ( * ). Não é isso que você espera.

Você deseja tratar $* como uma variável (nesse caso, com aspas duplas), então feche a string com aspas simples na frente e abra depois:

grep -E '*'"$*"'*' ~/.dotfiles/zsh/aliases.zsh

Mas eu não vejo a razão para essas estrelas (você não quer grep para as estrelas, não é?), para mim parece que você pode simplesmente simplificar isso para

grep -E "$*" ~/.dotfiles/zsh/aliases.zsh
    
por 26.06.2016 / 14:14