Subshells avançados de Linux com exemplos
- 792
- 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
Subshells avançados de Linux com exemplos 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