Subshells avançados de Linux com exemplos
- 765
- 103
- Ms. Travis Schumm
Se você ler nossas subs -grandes do Linux anteriores para iniciantes com exemplos de exemplos ou já tiver experiência com sub -explosões, você sabe que as subs -grandes são uma maneira poderosa de manipular os comandos do Bash embutido e de maneira sensível ao contexto.
Neste tutorial, você aprenderá:
- Como criar comandos de subshell mais avançados
- Onde você pode empregar sub -explosões mais avançadas em seu próprio código
- Exemplos de comandos de subshell mais avançados
Requisitos de software e convenções usadas
Categoria | Requisitos, convenções ou versão de software usada |
---|---|
Sistema | Independente da distribuição Linux |
Programas | Linha de comando Bash, sistema baseado em Linux |
Outro | Qualquer utilidade que não esteja incluída no shell bash por padrão pode ser instalada usando sudo apt-get install utility-name (ou yum em vez de apt-get) |
Convenções | # - requer que o Linux -Commands seja executado com privilégios de raiz diretamente como usuário root ou por uso de sudo comando$-exige que o Linux-Commands seja executado como um usuário não privilegiado regular |
Exemplo 1: Arquivos de contagem
$ se [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; Então o eco "encontrou uma ou mais ocorrências de arquivos [a-z]*!"; Fi
Aqui temos um se
declaração com o seu primeiro valor de comparação, uma subshell. Isso funciona bem e oferece uma grande quantidade de flexibilidade quando se trata de escrever se
declarações. É diferente que o binário (verdadeiro ou falso) como operação de por exemplo Se Grep -q 'Search_term' ./docfile.TXT
declaração. Em vez disso, é avaliado por si só como uma comparação padrão (combinada com o maior que eu zero -GT 0
cláusula).
A subshell tenta os arquivos de lista de diretórios nomeados [a-z]*
, eu.e. arquivos começando com pelo menos uma letra no a-z
alcance, seguido por qualquer personagem subsequente. É seguro de erro adicionando 2>/dev/nulo
- eu.e. Qualquer erro exibido (em stderr
- a saída de erro padrão, significada pelo 2
) será redirecionado >
para /dev/null
- eu.e. O dispositivo nulo Linux - e, portanto, ignorado.
Finalmente passamos a entrada do LS para wc -l
que contarão para nós quantas linhas (ou neste caso, arquivos) foram vistos. Se o resultado foi mais do que 0, a nota informativa será mostrada.
Observe como o contexto em que o subshell está operando é variado. Em primeiro lugar, neste caso, a subshell está trabalhando dentro do diretório de trabalho atual (i.e. $ PWD
) que é notavelmente também o padrão eu.e. Subshells por padrão Iniciar com seu próprio ambiente PWD
definido para o diretório de trabalho atual. Em segundo lugar, a subshell está trabalhando dentro do contexto de um se
declaração.
Nenhuma saída é gerada por este comando, pois está sendo executado dentro de um diretório vazio. No entanto, observe que o fato de que nenhuma saída é gerada também significa que nossa supressão de erros está funcionando. Vamos verificar isso:
$ se [$ (ls [a -z]* | wc -l) -gt 0]; Então o eco "encontrou uma ou mais ocorrências de arquivos [a-z]*!"; fi ls: não pode acessar '[a-z]*': nenhum arquivo ou diretório
Podemos ver como a remoção da supressão de erro funcionou no exemplo anterior. Vamos criar um arquivo e ver como o nosso liner se executa:
$ touch a $ se [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; Então o eco "encontrou uma ou mais ocorrências de arquivos [a-z]*!"; Fi encontrou uma ou mais ocorrências de arquivos [a-z]*!
Ótimo, parece que nosso script de uma linha tem um bom desempenho. Vamos adicione um arquivo secundário e ver se podemos melhorar a mensagem
$ touch b $ se [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; Então o eco "encontrou uma ou mais ocorrências de arquivos [a-z]*!"; Fi encontrou uma ou mais ocorrências de arquivos [a-z]*! $ se [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; Então o eco "encontrou exatamente $ (ls [a-z]* 2>/dev/null | wc -l) ocorrências de [a-z]* arquivos!"; Fi encontrou exatamente 2 ocorrências de arquivos [a-z]*!
Aqui vemos que a adição de um segundo arquivo (por toque b
) não faz nenhuma diferença (como visto no primeiro se
comando), a menos que alteremos a saída para realmente relatar quantos arquivos foram encontrados inserindo uma subshell secundária na saída.
No entanto, isso não é codificado de maneira ideal; Nesse caso, duas sub -explosões requerem execução (o custo de uma criação de subshell é muito mínimo, mas se você tiver muitas sub -rotas sendo criadas em alta frequência, o custo é importante), e a listagem diretamente é solicitada duas vezes (gerando E/S adicional e E/S e desacelerando nosso código para a velocidade do subsistema de E/S e o tipo de disco usado). Vamos colocar isso em uma variável:
$ Count = "$ (ls [a -z]* 2>/dev/null | wc -l)"; se [$ count -gt 0]; Então o eco "encontrou exatamente $ count ocorrências de [a-z]* arquivos!"; Fi encontrou exatamente 2 ocorrências de arquivos [a-z]*!
Ótimo. Este é o código mais ideal; Uma única subshell é usada e o resultado é armazenado em uma variável que é usada duas vezes, e apenas uma única recuperação de listagem de diretório de disco é necessária. Observe também que esta solução pode ser mais segura por threads.
Por exemplo, no se
Declaração que teve duas sub-grandes, se, no tempo entre a execução dessas subshells, um terceiro arquivo foi criado, o resultado pode parecer assim: Encontrou exatamente 3 ocorrências de arquivos [a-z]*!
enquanto o primeiro se
declaração (usando o primeiro subshell) realmente se qualificou em Se 2 -gt 0
- eu.e. 2. Faria pouca diferença neste caso, mas você pode ver como em alguma codificação isso pode se tornar muito importante.
Exemplo 2: Subshells para cálculo
$ touch z $ echo $ [$ (data + %s) - $ (stat -c %z ./z)] 1 $ echo $ [$ (data + %s) - $ (stat -c %z ./z)] 5
Aqui criamos um arquivo, ou seja, z
, e posteriormente descobriu a idade do arquivo em segundos usando o segundo comando. Alguns segundos depois, executamos o comando novamente e podemos ver que o arquivo agora tem 5 segundos de idade.
O data +%s
O comando nos dá o tempo atual em segundos desde a Epoch (1970-01-01 UTC) e stat -c %z
nos dá os segundos desde a época do arquivo que foi criado anteriormente e agora referenciado aqui como ./z
, Então, tudo o que precisamos posteriormente é subtrair esses dois um do outro. Colocamos o data +%s
Primeiro, pois esse é o número mais alto (o horário atual) e, portanto, calcule corretamente o deslocamento em segundos.
O -c
opção para Estado
simplesmente indica que queremos uma formatação de saída específica, neste caso %Z
, Ou, em outras palavras, o tempo desde a época. Para data
A sintaxe para a mesma ideia é +%s
, embora em conexão com o tempo atual e não esteja relacionado a um arquivo específico.
Exemplo 3: Subshells dentro de sed e outras ferramentas
$ echo '0'> a $ sed -i "s | 0 | $ (whoami) |" ./A $ CAT A ROEL
Como você pode ver, podemos usar uma subshell em quase qualquer comando que executamos na linha de comando.
Nesse caso, criamos um arquivo a
com conteúdo como 0
e posteriormente em linha substitua o 0
para $ (whoami)
que, quando a subshell é executada como o comando está sendo analisada, substituirá o nome de usuário Roel
. Cuidado para não usar citações únicas, pois isso tornará a sub -Shell inativa porque a string será interpretada como texto literal:
$ echo '0'> a $ sed -i 's | 0 | $ (whoami) |' ./a $ cat a $ (whoami)
Observe aqui que o sed
Sintaxe Ativada (S | 0 |… |
) ainda funciona corretamente (!), enquanto a funcionalidade da subshell da Bash $ ()
nao fiz!
Exemplo 4: Usando avaliar e um loop
$ Loops = 3 $ echo 1… $ loops 1… 3 $ avaliar echo 1… $ loops 1 2 3 $ para i em $ (echo 1… $ loops); eco "$ i"; feito 1… 3 $ para i em $ (avaliar eco 1… $ loops); eco "$ i"; feito 1 2 3
Este exemplo, embora não seja a maneira ideal de executar um direto para
Loop, mostra -nos algumas maneiras de integrar sub -grandes, mesmo dentro de loops. Nós usamos o aval
declaração para processar o 1… 3
texto em 1 2 3 que pode ser usado diretamente dentro do para
Cláusula de repetição de loop.
Às vezes, o uso de sub-grandes e fornecendo informações em linha em linha através de sub-shells nem sempre é evidente e pode exigir alguns testes, ajustes e ajustes finos antes que as sub-capítulos sejam executadas conforme esperado. Isso é normal e muito alinhado com a codificação de bash normal.
Conclusão
Neste artigo, exploramos alguns exemplos mais aprofundados e avançados de usar subs-grandes em Bash. O poder das subshells permitirá que você transforme a maioria dos scripts de uma linha em versões muito mais poderosas, sem mencionar a possibilidade de usá-las dentro de seus scripts. Quando você começa a explorar subs -grandes e encontra algumas maneiras legais de usá -las, poste -as abaixo nos comentários!
Aproveitar!
Tutoriais do Linux relacionados:
- Coisas para instalar no Ubuntu 20.04
- Coisas para fazer depois de instalar o Ubuntu 20.04 fossa focal linux
- Subshells Linux para iniciantes com exemplos
- Uma introdução à automação, ferramentas e técnicas do Linux
- Como usar as sub -mais de bases dentro das declarações if if
- Coisas para fazer depois de instalar o Ubuntu 22.04 Jellyfish…
- Comandos Linux: os 20 comandos mais importantes que você precisa para…
- Comandos básicos do Linux
- Download do Linux
- Instale Arch Linux na estação de trabalho VMware