Posso pegar bash para ignorar a liderança ':' quando está presente?

3

Muitas vezes, se estou trabalhando no bash (no macOS), também estou trabalhando no (Mac) Vim, alternando entre os dois. Um erro comum que eu faço depois de mudar do Vim para o Terminal é incluir um cólon inicial antes do comando. Eu vou :cd /path/to/project/dir/ no Vim e, em seguida, mudo para o Terminal e digite exatamente a mesma coisa, exceto, é claro, eu não deveria começar com dois pontos.

Então, eu não sei de quando um comando bash deve começar com dois pontos, e toda vez que eu faço isso eu não quero. Então, existe uma maneira de obter o bash para ignorar completamente os dois pontos se for o primeiro caractere em um comando e interpretar :cd ... as cd ... ?

    
por Chuck 12.07.2016 / 08:52

1 resposta

10

bash(1) chamará a função command_not_found_handle() se definido e o comando a ser executado não for encontrado. Se você ainda não estiver usando esse recurso (como o pacote command-not-found no Ubuntu), você pode usá-lo para retirar o sinal de dois pontos e tentar novamente:

command_not_found_handle() {
    if [[ "${1:0:1}" != : ]]; then
        printf "%s: %s: command not found\n" "$0" "$1" >&2
        return 127
    else
        "${1/#:}" "${@:2}"
    fi
}

Coloque essa função no seu .bashrc . Então, quando um comando que começa com dois pontos não for encontrado, ele tirará o cólon da frente e tentará novamente.

Edit: Vou explicar um pouco mais, já que há algumas expansões incomuns aqui.

Em primeiro lugar, conforme observado nos comentários, command_not_found_handle é um recurso do bash 4. Bash 4 foi lançado em fevereiro de 2009. A função command_not_found_handle é chamada com argumentos que é o comando não encontrado e os argumentos desse comando. ou seja, $1 é o comando não encontrado e $2 em diante são os argumentos para o comando que não foi encontrado. Isso é descrito em COMANDO EXECUÇÃO na página man.

"${1:0:1}" é uma expansão que recebe uma substring de $1 , da posição 0 de comprimento 1. Ou seja, extrai o primeiro caractere de $1 , em que $1 é o comando que não foi encontrado. Isso está documentado em Expansão do Parâmetro na página man como ${parameter:offset:length} .

Se o primeiro caractere de $1 não for dois pontos, imprimimos um erro e retornamos com um valor de saída 127. 127 é o código de saída que o bash usa quando não encontra o comando para executar conforme documentado em EXECUÇÃO DE COMANDO na página man.

"${1/#:}" expande para $1 com qualquer cólon inicial removido. Se não houver cólon no início, isso equivale a um $1 simples, mas sabemos que ele começa com dois pontos de qualquer maneira devido à ramificação da condição em que estamos. Essa expansão está documentada em Expansão do Parâmetro na página man na seção ${parameter/pattern/string} .

"${@:2}" expande para os parâmetros posicionais a partir do segundo. Essa expansão está documentada em Expansão do Parâmetro na página man na seção ${parameter:offset} , como um caso especial para matrizes e @ . Ou seja, em vez de extrair uma substring, ela se expande para elementos da matriz.

O resultado final é que, se um comando não encontrado for executado e tiver dois pontos à esquerda, removeremos os dois pontos para formar um novo comando e passaremos os argumentos originais para o novo comando. Isso terminará funcionando recursivamente, como se a segunda tentativa de executar um comando não fosse encontrada, command_not_found_handle() será executado novamente. Isso significa que você pode executar :::mkdir e ainda vai acabar executando mkdir .

    
por 12.07.2016 / 10:19

Tags