Como alguém pode escrever um script que aceite entrada de um argumento de nome de arquivo ou de stdin?
por exemplo, você poderia usar less
dessa maneira. um pode executar less filename
e equivalentemente cat filename | less
.
existe uma maneira fácil e imediata de fazer isso? ou preciso reinventar a roda e escrever um pouco de lógica no script?
command-line
bash
stdin
Gilad Hoch
fonte
fonte
Respostas:
Se o argumento do arquivo for o primeiro argumento para o seu script, teste se existe um argumento (
$1
) e se é um arquivo. Caso contrário, leia a entrada de stdin -Portanto, seu script pode conter algo como isto:
por exemplo, então você pode chamar o script como
ou
Editar Algumas explicações do script:
[ $# -ge 1 -a -f "$1" ]
- Se pelo menos um argumento da linha de comando ($# -ge 1
) AND (-a operator) o primeiro argumento for um arquivo (-f testa se "$ 1" é um arquivo), o resultado do teste é verdadeiro.&&
é o operador lógico AND do shell. Se teste for verdadeiro, atribuainput="$1"
ecat $input
exibirá o arquivo.||
é o operador OR lógico do shell. Se o teste for falso, os comandos a seguir||
serão analisados. entrada é atribuída a "-". O comandocat -
lê no teclado.Resumindo, se o argumento do script for fornecido e for um arquivo, a entrada variável será atribuída ao nome do arquivo. Se não houver argumento válido, o gato lê no teclado.
fonte
&& input="$1" || input="-"
faz e por que está fora dotest
operador?$@
)?read
lê da entrada padrão. Redirecioná-lo do arquivo (./script <someinput
) ou através do pipe (dosomething | ./script
) não fará com que funcione de maneira diferente.Tudo o que você precisa fazer é percorrer todas as linhas da entrada (e isso não difere da iteração nas linhas do arquivo).
(código de amostra, processa apenas uma linha)
Irá ecoar a primeira linha da sua entrada padrão (através
<
ou|
).fonte
Você não menciona qual shell planeja usar, portanto, assumirei o bash, embora essas sejam coisas bastante comuns entre os shells.
Argumentos de arquivo
Os argumentos podem ser acessados através das variáveis
$1
-$n
($0
retorna o comando usado para executar o programa). Digamos que eu tenha um script quecat
exiba n número de arquivos com um delimitador entre eles:Nesse caso, estamos passando um nome de arquivo para cat. No entanto, se você quiser transformar os dados no arquivo (sem gravá-los e gravá-los explicitamente), também poderá armazenar o conteúdo do arquivo em uma variável:
Leia de stdin
Quanto à leitura do stdin, a maioria dos shells possui um padrão bastante
read
embutido, embora existam diferenças na forma como os prompts são especificados (no mínimo).A página de manual do Bash builtins tem uma explicação bastante concisa
read
, mas eu prefiro a página do Bash Hackers .Simplesmente:
Várias variáveis
Para definir várias variáveis, basta fornecer vários nomes de parâmetros para
read
:read
colocará uma palavra de stdin em cada variável, despejando todas as palavras restantes na última variável.Se menos palavras forem inseridas do que variáveis, as demais variáveis ficarão vazias (mesmo se definidas anteriormente):
Comandos
Eu uso
-p
frequentemente o sinalizador para um prompt:Nota: ZSH e KSH (e talvez outros) usam uma sintaxe diferente para avisos:
Valores padrão
Isso não é realmente um
read
truque, mas eu o uso muito em conjunto comread
. Por exemplo:Basicamente, se a variável (resposta) existir, retorne a si mesma, mas se estiver vazia, retorne o seguinte parâmetro ("N").
fonte
A maneira mais simples é redirecionar você mesmo:
Ou se você preferir a forma mais concisa:
Agora, o restante do seu script pode ser lido no stdin. É claro que você pode fazer o mesmo com a análise de opções mais avançadas, em vez de codificar a posição do nome do arquivo como
"$1"
.fonte
exec
tentará executar o argumento como um comando que não é o que queremos aqui.if [ "$1" ] ; then exec < "$1" ; fi
em um script de teste e ele fornece uma mensagem de erro porque o comando é desconhecido. Mesmo com a forma concisa.use (ou encadeie) algo que já se comporte dessa maneira e use
"$@"
digamos que eu quero escrever uma ferramenta que substitua a execução de espaços no texto por guias
tr
é a maneira mais óbvia de fazer isso, mas ela só aceita stdin, por isso temos que nos encadearcat
:por exemplo, em que a ferramenta usada já se comporta dessa maneira, poderíamos reimplementá-lo com
sed
:fonte
Você também pode fazer:
Para obter mais truques de substituição de parâmetros no Bash, consulte isso .
fonte
uglifyjs < /dev/stdin
e funciona maravilhosamente!Você também pode simplificar e usar esse código
Quando você cria um arquivo de script pass_it_on.sh com este código,
Você pode correr
e todo o conteúdo do stdin será simplesmente expelido para a tela.
Como alternativa, use esse código para manter uma cópia do stdin em um arquivo e depois enviá-lo para a tela.
e aqui está outro exemplo, talvez mais legível, explicado aqui:
http://mockingeye.com/blog/2013/01/22/reading-everything-stdin-in-a-bash-script/
Diverta-se.
RaamEE
fonte
A maneira mais simples e compatível com POSIX é:
que é equivalente a
${1:--}
.Em seguida, leia o arquivo como de costume:
fonte