Zsh possivelmente adicionando aspas ao valor da variável (funciona no bash embora)

2

Sou relativamente novo no zsh (deslocado ontem do bash)

Eu tive uma função bash no bash como

vl() { cmd='echo $1 | sed -r 's/(.+):([0-9]+).+/ +/g''; vim $cmd }

Isso basicamente converte um argumento como:

vl ./manifests/production/test.pp:387:foobar  # A output of $grep -iHn test 

para

vim ./manifests/production/test.pp +387   #Aim is to open file at line-number 387

A mesma função no zsh não funciona como esperado. Ele abre um arquivo chamado ./manifests/production/test.pp +387 no vim em vez de abrir um arquivo chamado ./manifests/production/test.pp com +387 anexado a ele. Parece que está adicionando as aspas a $cmd .

Seria ótimo se alguém explicasse o que está acontecendo aqui. Obrigado

    
por Abhijeet Rastogi 14.10.2013 / 08:00

2 respostas

6

Em shells normais no estilo Bourne, como Bourne shell, dash, ksh e bash, a sintaxe $variable significa “pegar o valor da variável, dividi-la em palavras separadas onde os caracteres de IFS aparecem e tratar cada palavra como um padrão curinga de nome de arquivo e expandi-lo se corresponder a um ou mais arquivos ”. Se variable for uma matriz, isso acontece com o primeiro elemento da matriz e os outros elementos são ignorados.

Em zsh, a sintaxe $variable significa "pegar o valor da variável, exceto removê-lo se estiver vazio". Se variable for uma matriz, isso acontece com todos os elementos da matriz. Os entusiastas de Zsh consideram a maneira zsh superior.

Em zsh, você pode escrever $=variable para realizar a divisão de palavras. Esta não é a melhor maneira de fazer o que você está fazendo, no entanto. Sua função bash não suporta espaços em branco em nomes de arquivos, e usar $=variable em zsh também não. Aqui está uma maneira diferente de analisar o argumento que funciona tanto no bash quanto no zsh e lida com qualquer caractere, exceto : em um nome de arquivo. Se o argumento contiver dois dois-pontos, tudo após o primeiro cólon será removido e a parte entre o primeiro cólon e o segundo cólon será anexada como um argumento separado precedido por um sinal + . É um pouco mais longo que o seu código, mas menos difícil de entender, e não engasga na primeira dica de um espaço em um nome de arquivo.

vl () {
  local suffix
  case $1 in
    *:*:*) suffix=${1#*:};; set -- "${1%%:*}" "+${suffix%%:*}";;
  esac
  vim "$@"
}
    
por 15.10.2013 / 03:22
2

É complicado :) Uma solução alternativa é definir a função assim:

vl() { cmd=$(echo $1 | sed -r 's/(.+):([0-9]+).+/ +/g'); eval "vim $cmd"; }

Note que a solução alternativa é o uso de eval , não as outras pequenas modificações que eu tive que fazer, porque eu não tenho o requerido stackexchange editing-fu 8 -)

    
por 14.10.2013 / 12:46

Tags