Qual é o significado de um trailing “:” (dois pontos) em * nix? [fechadas]

1

Atualmente, estou seguindo um tutorial sobre scripts de shell localizado aqui: link e acredito que meu script corresponde exatamente a um. No entanto, quando tento executar o exemplo, minha saída não corresponde. Como não quero ser vago e simplesmente perguntar "por que isso não funciona?", Vou focar na parte que não entendo: por que há um ":" após o comando testlogin: ? Eu tenho lido muitos fóruns que discutem o significado de " : " (com espaços em ambos os lados) e também um líder ":" , mas nenhum menciona o uso do cólon atrasado. Qual é o significado nesse contexto? E se isso for um erro de digitação, alguém pode me ajudar a encontrar outro erro de digitação no exemplo que pode estar fazendo com que ele não seja executado corretamente?

Qualquer ajuda seria muito apreciada!

o código (copiado exatamente do site linkado acima) está abaixo:

#testlogin
useron(){
if ( who | grep $1 > /dev/null)
then echo $1 is logged in
else echo $1 is not logged in
fi 
}
if test $# != 1
then echo testlogin: username
else useron
fi

e a saída de

paul@paul-LC22UP:~$ .testlogin paul
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
is no logged in
    
por Paul 18.01.2016 / 01:30

2 respostas

8

testlogin não é um comando aqui, mas um argumento para echo . O comando completo é:

 echo testlogin: username

echo apenas mostra o texto que você deu a STDOUT. Portanto, o cólon não tem significado especial, é parte da saída textual de echo . Esta é a saída se você chamar o script com o número incorreto de argumentos:

$ ./testlogin
testlogin: username
$ ./testlogin fred bill adam
testlogin: username

Esta é uma saída estranha, mas não necessariamente um erro de digitação. Eu normalmente esperaria algo mais ao longo das linhas:

$ ./testlogin
Usage: testlogin username

A razão pela qual todo o script não funciona é porque o autor cometeu um erro sutil ao chamar a função useron , e presumivelmente não testou o script antes de publicá-lo (ou eles teriam notado o mesmo erro fez). $1 na função useron é o primeiro argumento para essa função , não para o script inteiro; mas como useron não foi chamado com nenhum argumento, essa é a string vazia e, portanto, acaba executando o comando:

$ who | grep

que fornecerá grep s informações de uso e sempre acionará a ramificação else da condição. Você pode corrigir isso passando o primeiro argumento para o script em useron da seguinte forma:

else useron $1
    
por 18.01.2016 / 01:59
1

O site ao qual você está vinculado tem qualidade muito baixa shell scripts .
Para responder à sua pergunta de antemão, os "dois pontos" não têm significado especial para o shell, é apenas parte de uma string a ser impressa na tela.

No entanto, o código na página tem essas falhas:

  • A questão mais importante que você deve aprender é "citar suas expansões". Isso é "Expansões de Parâmetros" (variável), mas também outras expansões.
    Esta é a principal razão pela qual estou escrevendo isso. É muito ruim adquirir o hábito de não citar expansões.

  • Não há menção ao mecanismo shebang em qualquer parte da página. (significa ter uma primeira linha como #! / bin / bash ou similar). Escrever scripts sem indicar o tipo de shell destinado a executá-los é uma fonte segura de bugs e problemas.

  • O número de linha 11 não possui o argumento usado para chamar a função. Deve ser algo como: else useron "$1" em vez de else useron

Depois desses três erros claros, podemos executar o script:

$ testlogin
testlogin: username

Como você pode ver, a string na linha 10 é impressa como no console.
O cólon final : não significa nada para o shell, o que fica claro quando a string é citada desta forma:

then echo "testlogin: username"

Na verdade, IMO, seria ainda mais explícito:

then echo "A parameter is needed, type something like 'testlogin: username'"

Agora, a execução do script sem um argumento imprime uma resposta útil.
E escrever um nome de usuário também funciona:

$ testlogin joe
joe is not logged in

O script com as alterações acima é:

#/bin/sh
useron(){
    if    ( who | grep "$1" > /dev/null)
    then  echo "$1 is logged in"
    else  echo "$1 is not logged in"
    fi
}

if    test "$#" != "1"
then  echo "Parameter missing, type something like 'testlogin: username'"
else  useron "$1"
fi

Agora, para uma segunda rodada de problemas:

  • O comando test externo caiu em desuso na maioria dos shells.
    Ele foi substituído pelo equivalente totalmente [ ou por [[ em shells mais modernos. A linha usada no script: if test "$#" != "1" deve ser substituída por:

    if    [ "$#" != "1" ]
    
  • Agora chegamos ao estilo de escrever. Nos tempos modernos, é mais comum ver o roteiro escrito assim (mas isso é uma questão de preferência pessoal):

#/bin/sh
useron(){
    if ( who | grep "$1" > /dev/null); then
        echo "$1 is logged in"
    else
        echo "$1 is not logged in"
    fi
}

if  [ "$#" != "1" ]; then
    echo "Parameter missing, type something like 'testlogin: username'"
else
    useron "$1"
fi
    
por 18.01.2016 / 03:17