Noções básicas sobre comandos read, echo e grep em uma linha de comando bash

Noções básicas sobre comandos read, echo e grep em uma linha de comando bash

Alguém pode explicar o que acontece nesta linha bash passo a passo? Sou novo aqui e estou tentando entender como esse código funciona, principalmente de echo:

read char; echo -e "YES\nNO\n" | grep -i $char

Responder1

Os comandos na linha lêem uma string na variável char, provavelmente de forma interativa do usuário.

O pipeline echo+ greptenta determinar se a string inserida é afirmativa ou não. Ele faz isso combinando as palavras YESe NOcom a string inserida (com a string inserida como padrão), sem distinção entre maiúsculas e minúsculas. Se o usuário inserir um caractere maiúsculo ou minúsculo ou uma substring presente na palavra YES, o resultado será YES; se eles inserissem um caractere maiúsculo ou minúsculo ou uma substring presente na string NO, o resultado seria NO. Inserir algo como mayberesultaria em uma saída vazia.

A desvantagem dessa abordagem é que se o usuário inserir, por exemplo, ., ambos YESe NOcorresponderiam a greptratariam o ponto como uma expressão regular que corresponde a qualquer caractere. Como $charnão está entre aspas na chamada para grep, também teria o potencial de causar um ataque de negação de serviço contra a máquina se o usuário inserir um padrão globbing de shell, como /*/*/*/*/../../../../*/*/*/*input (exemplo retirado deImplicações de segurança de esquecer de citar uma variável em shells bash/POSIX). Você também pode causar confusão na saída do comando digitando, por exemplo -r -o -e . /(irá gerar todos os caracteres de todos os arquivos não binários em uma linha por si só, precedida pelo nome do caminho do arquivo do qual faz parte).

O código que você mostra é "estranho e incomum", pois usa a entrada do usuário como algo que é essencialmentecódigo, ou seja, ele usa a entrada do usuário como umpadrãoe testa estáticadadoscontra esse padrão variável. Isso é o oposto do que normalmente se faz, que é pegar a entrada do usuário e testar esses dados variáveis ​​em relação a um padrão estático.

É mais comum usar código semelhante ao seguinte:

read -p 'Yes/[N]o: ' yesno
if [[ $yesno == [Yy]* ]]; then
   # code for affirmative
else
   # code for non-affirmative
fi

O código acima lê uma string do usuário e testa se ela começa com um you um Ycaractere. O primeiro ramo da ifinstrução seria usado se isso acontecesse, mas elsecaso contrário, o padrão seria pegar o ramo.

Obviamente, você também pode testar o Word inteiro YES, ou [Yy][Ee][Ss]uma correspondência que não diferencia maiúsculas de minúsculas, ou fazer um loop de entrada adequado com verificação:

while true; do
    read -p 'Yes/No: ' yesno

    if [ "$yesno" = Yes ] || [ "$yesno" = No ]; then
        break
    fi

    echo 'Please enter "Yes" or "No"' >&2
done

# $yesno is either Yes or No here

(ou algo semelhante).

Observe como os dois códigos de exemplo acima usam a entrada do usuário exclusivamente como dados e nunca como padrão.

Reescrever seu comando original minimamente para algo um pouco idiomático (mas funcionalmente diferente e provavelmente não infalível) o transformaria em

read yesno; printf '%s\n' "${yesno^^}" | grep -i -w -E 'yes|no'

Isso retornaria letras maiúsculas YESou NOse o usuário digitasse yesou no. Isso é funcionalmente diferente, pois exige que o usuário digite algo mais do que apenas ea yes, por exemplo.

Responder2

Bem, vamos analisar cada comando por vez:

read char

Isso lerá a entrada padrão (normalmente o seu teclado, mas pode ser um arquivo indireto ou um fluxo canalizado; veja abaixo) e colocará os dados recebidos em uma variável chamada char.

echo -e "YES\nNO\n"

echoexibirá na saída padrão (normalmente o terminal) os parâmetros fornecidos. A -eopção (frequentemente, mas nem sempre; echoé meio problemática em relação à implementação consistente) permitirá que você eescape de certos caracteres para fazer alguma formatação rudimentar. Nesse caso, está usando \n, que é um escaped n, que é uma abreviação de newline.

grep -i $char

grepé uma ferramenta para pesquisar a entrada fornecida para ver se há alguma correspondência para o padrão fornecido. A -iopção informa que é uma ipesquisa que não diferencia maiúsculas de minúsculas.

O |entre os comandos echoe grepé um "tubo". Isso conecta a saída do primeiro comando à entrada do segundo, o que significa que grepestaremos pesquisando neste corpus o padrão refletido no conteúdo da variável char:

YES
NO

O resultado prático desta sequência de comandos é observar a entrada fornecida (assumida com base no nome da variável como sendo um único caractere, mas isso não é verificado). Se este caractere for Y, E, S, y, e, ou s, a saída será YES. Se este caractere for N, O, nou o, a saída será NO. No entanto, se (por exemplo) a entrada for yoou ne, nada será gerado.

Conforme observado anteriormente, a presunção de que a entrada é um caractere não é verificada. Este não é o único antipadrão na sequência de comandos de exemplo fornecida. Por exemplo, as variáveis ​​não estão sendo citadas; e uma ferramenta de expressão regular ( grep) está sendo usada sem que a entrada seja examinada para curingas regex.

Responder3

Um "caractere" (em vez de: string) é lido de /dev/stdin. Significado: você digita.

Em seguida, duas linhas são enviadas para /dev/stdout. Ou seja, seu console.

E através do pipe (o "|") isso é então digitado para a versão que não diferencia maiúsculas de minúsculas da sua entrada.

Isso significa que se você inserir "bar", ele simplesmente terminará sem qualquer saída aparente, mas se você inserir, digamos, "y", a linha "YES" será exibida, provavelmente até destacando o "Y"

informação relacionada