Expansões de shell de bash expansão, expansão de parâmetros e mais

Expansões de shell de bash expansão, expansão de parâmetros e mais
Neste artigo, abordaremos todas as características básicas da expansão da Bash Shell. Algumas das expansões mais complexas e interessantes são a expansão e a expansão dos parâmetros, que têm muitos recursos e opções poderosos, mas apenas dominados ao longo do tempo por programadores e pessoas do Linux DevOps. A divisão de palavras também é bastante interessante e às vezes esquecida. Nome do arquivo, expansão aritmética e substituição variável são bem conhecidas. Abordaremos inúmeros tópicos e mostraremos exemplos do comando e sintaxe mais útil para cada sintaxe. Então vamos começar.
  • Ambiente
  • Substituição de comando
  • Substituição do processo
  • Substituição variável
  • Expansão do aparelho
  • Expansão de parâmetros
  • Parâmetros posicionais
  • Expansão Tilde
  • Substituição aritmética
  • Divisão de palavras
  • Expansão do nome do arquivo
  • Conclusão

Ambiente

Para testar todos os recursos de expansão do Bash Shell, precisamos garantir que estamos executando uma versão recente do Bash. Abaixo está as informações do sistema para este artigo. Os testes deste artigo estão sendo executados no Ubuntu 19.10 como mostrado abaixo.

$ uname -a
Linux Instância 1 5.3.0-1014-GCP #15-Ubuntu SMP Ter 3 04:14:57
UTC 2020 x86_64 x86_64 x86_64 gnu/linux

A versão bash para esses testes é a versão 5, o que é bastante recente. As versões mais antigas do Bash estão perdendo vários recursos.

$ Bash -Versão
GNU Bash, versão 5.0.3 (1) -Elease (X86_64-PC-Linux-Gnu)
Copyright (C) 2019 Free Software Foundation, Inc.
Licença GPLV3+: GNU GPL Versão 3 ou mais tarde

Substituição de comando

A substituição de comando permite a execução de um ou vários comandos e captura saídas e ações desses comandos e incluí -los em outro comando, tudo em uma linha ou menos linhas do que executar todos os comandos separadamente. A substituição de comando tem duas sintaxes; A sintaxe mais popular é a sintaxe de backtick, onde o comando a ser executado é fechado em dois backquotes ou backticks. A outra sintaxe, que é igualmente poderosa, encerra os comandos na sintaxe $ () e a saída pode ser usada a partir dessa nova expansão. Vejamos vários exemplos de substituição de comando abaixo.

Substituição de comando simples usando a sintaxe $ () para executar o comando de data.

$ echo $ (data)
Qua 18 de março 01:42:46 UTC 2020

Substituição de comando simples usando a sintaxe do backtick para executar o comando date.

$ eco 'data'
Qua 18 de março 01:43:17 UTC 2020

Usar o operador de stdin no início da sintaxe de substituição de comando é uma maneira sofisticada de ler o texto de um arquivo em uma variável e usá -la em um comando no shell como abaixo.

$ eco "Hello World"> MyText
$ echo $ (< mytext)
Olá Mundo

Leia um arquivo em uma variável a ser usada em um comando usando o comando CAT e substituição de comando.

$ eco "Hello World"> MyText
$ eco $ (gato mytext)
Olá Mundo

O mesmo que acima, leia um arquivo e use -o na substituição de comando usando backticks e comando gato.

$ eco "Hello World"> MyText
$ eco 'gato mytext'
Olá Mundo

Combine a substituição de comando incorporada com outra substituição de comando usando $ () e backticks juntos

$ echo 'echo $ (data) | corte -d "" -f 1'> myfile
$ Cat MyFile
qua

Substituição de comando incorporada dentro de outra usando duas operações de sintaxe $ ()

$ echo "Hoje é $ (echo $ (data) | corte -d" "-f 1)"> myfile
$ Cat MyFile
Hoje é casado

Use a saída de um comando como argumentos em outro comando, com a sintaxe do backtick. Obteremos uma lista de arquivos executando o CAT que contém um arquivo por linha e depois passará para o comando rm que removerá cada arquivo

$ toque um; Toque em dois
$ echo um> myfiles; eco dois >> myfiles
$ rm 'gato myfiles'

O mesmo que acima, mas com a sintaxe $ (), passe a saída do comando de CAT para o comando rm para excluir arquivos.

$ toque um; Toque em dois
$ echo um> myfiles; eco dois >> myfiles
$ rm $ (gato myfiles)

Armazene a saída de um comando CAT em uma variável e depois passe pela variável para que você possa ver mais claramente o que está acontecendo.

$ toque um; Toque em dois
$ echo um> myfiles; eco dois >> myfiles
$ Myfiles = $ (gato myfiles)
$ para f em $ myfiles; eco $ f; rm $ f; feito
um
dois

O mesmo que acima, mas use a sintaxe de backticks para executar o comando CAT e armazenar a saída em uma variável e depois percorrer os arquivos na variável.

$ toque um; Toque em dois
$ echo um> myfiles; eco dois >> myfiles
$ Myfiles = 'gat myfiles'
$ para f em $ myfiles; eco $ f; rm $ f; feito
um
dois

Use a substituição de comando com o operador STDIN para ler uma linha de arquivo por linha em uma variável e depois percorrer as palavras posteriores da variável

$ toque um; Toque em dois
$ echo um> myfiles; eco dois >> myfiles
$ Myfiles = $ (< myfiles)
$ para f em $ myfiles; eco $ f; rm $ f; feito
um
dois

Substituição do processo

A substituição do processo é um recurso documentado do Bash; É bastante enigmático na minha opinião. Na verdade, eu não encontrei muitos casos de bom uso para recomendar para isso. Um exemplo está incluído aqui para completar, onde usamos a substituição do processo para obter a saída de um comando e depois usá -lo outro comando. Imprimiremos a lista de arquivos em ordem inversa com o comando de classificação neste exemplo depois de buscar arquivos do comando ls.

$ toque um.TXT; Toque em dois.TXT; Toque em três.TXT
$ Sort -R <(ls *txt)
dois.TXT
três.TXT
um.TXT

Substituição variável

Substituição variável é o que você pode considerar o uso básico de variáveis ​​e substituir o valor da variável quando for referenciado. É bastante intuitivo, alguns exemplos são fornecidos abaixo.

Atribuição e uso simples de variáveis ​​onde colocamos uma string na variável x e depois a imprimimos para stdout

$ X = 12345
$ echo $ x
12345

Verifique se uma variável está atribuída algo ou nulo, nesse caso, ela é atribuída, então nós a imprimimos para stdout

$ X = 12345
$ se [-z "$ x"]; então eco "x é nulo"; else eco $ x; fi
12345

Verifique se uma variável recebe algo ou nulo, neste caso, não está definido, então imprimimos “é nulo” em vez do valor.

$ unset x
$ se [-z "$ x"]; então eco "x é nulo"; else eco $ x; fi
X é nulo

Expansão do aparelho

A expansão do BRACE é um recurso super poderoso do Bash que permite escrever scripts e comandos mais compactos. Tem muitos recursos e opções diferentes descritos abaixo. Dentro do aparelho, sua sintaxe é interpretada em uma sintaxe mais detalhada, dependendo quando você entra no aparelho encaracolado. Vejamos vários exemplos de expansão.

Cada versão dos itens da lista no aparelho é executada. Então, passamos de um comando de eco e imprimimos 3 versões da palavra abaixo separadas por espaços.

$ echo a, m, p _warehouse
A_WAREHOUSE M_WAREHOUSE P_WAREHOUSE

Expressões na expansão causam execução várias vezes. Para provar isso, usamos a data e o comando do sono para validar que o comando de data é executado uma vez para cada iteração do padrão na expansão da cinta.

$ echo a, m, p _ $ (data; sono 1)
A_SUN 22 de março 18:56:45 UTC 2020 M_SUN 22 de março 18:56:46 UTC
2020 p_sun 22 18:56:47 UTC 2020

Expansões usando números com… farão com que números seqüenciais sejam expandidos em uma sequência numérica

$ echo 1… 8 _warehouse
1_warehouse 2_warehouse 3_warehouse 4_warehouse 5_warehouse 6_warehouse 7_warehouse
8_Warehouse

Expansão de chave de ordem reversa com sequência de números

$ echo 8… 1 _warehouse
8_Warehouse 7_Warehouse 6_Warehouse 5_Warehouse 4_Warehouse 3_Warehouse 2_Warehouse
1_warehouse

Usando um valor de incremento opcional para especificar os incrementos numéricos da expansão da cinta

$ echo 1… 9… 3 _warehouse
1_warehouse 4_warehouse 7_warehouse

A expansão da suporte lexicográfico irá iterar através de cartas no alfabeto na ordem do local

$ echo a… e _warehouse
A_WAREHOUSE B_WAREHOUSE C_WAREHOUSE D_WAREHOUSE E_WAREHOUSE

Expansão de cinta lexicográfica de ordem reversa

$ echo e… a _warehouse
e_warehouse d_warehouse c_warehouse b_warehouse a_warehouse

A expansão da cinta lexicográfica com o incremento especificada irá a uma lista de caracteres do início para o ponto final, mas pula os caracteres de acordo com o valor de incremento

$ echo a… z… 5 _warehouse
a_warehouse f_warehouse k_warehouse p_warehouse u_warehouse z_warehouse

Expansão multiplicativa de cinta com 2 expansões de suporte em um comando

$ echo a… e 1… 5 _warehouse
A1_Warehouse A2_Warehouse A3_Warehouse A4_Warehouse A5_Warehouse B1_WareHouse
B2_WAREHOUSE B3_WAREHOUSE B4_WAREHOUSH B5_WAREHOUSE C1_WAREHOUSE C2_WAREHOUSE
C3_WAREHOUSE C4_WAREHOUSE C5_WAREHOUSH D1_WAREHOUSH D2_WAREHOUSH D3_WAREHOUSE
d4_warehouse d5_warehouse e1_warehouse e2_warehouse e3_warehouse e4_warehouse
e5_warehouse

Expansão de colméia para usar a mesma raiz duas vezes em um comando. Isso cria um foo.Arquivo TGZ TAR de um diretório sob nome Foo. É uma sintaxe útil onde você a está usando dentro de outro loop e deseja assumir que a base da palavra é usada várias vezes. Este exemplo mostra com alcatrão, mas também pode ser usado com MV e CP conforme este exemplo.

$ mkdir foo
$ touch foo/foo a… e
$ tar czvf foo .tgz,
foo/
foo/foob
foo/fooc
foo/fooa
Foo/comida
foo/fooe

Expansão de parâmetros

A expansão dos parâmetros também é uma boa sintaxe compacta com muitos recursos, como: Permitir que os scripts defina valores padrão para variáveis ​​ou opções não definidas, operações de substring de string, pesquisar e substituir substituições e outros casos de uso. Exemplos estão abaixo.
Verifique se há nulo e use o parâmetro se não for nulo ou o valor padrão. Nesse caso, X não é nulo, então será usado

$ X = 1
$ echo $ x: -2
1

Verifique se há nulo e use o parâmetro se não for nulo ou o valor padrão. Nesse caso, x é nulo, então o valor padrão será usado

$ unset x
$ echo $ x: -2
2

Verifique se a variável é nula e defina e ecoe -a se for nula. X é atribuído 2 e impresso $ x. Isso pode definir a variável e usá -la no comando com a sintaxe $ : =.

$ unset x
$ se [-z "$ x"]; então ecoar nulo; fi
NULO
$ echo $ x: = 2
2
$ se [-z "$ x"]; então ecoar nulo; else eco $ x; fi
2

A expansão da substring substituirá de um ponto de deslocamento um certo número de caracteres na string

$ X = "Hello World"
$ echo $ x: 0: 7
Olá w

Altere o deslocamento para o segundo caractere e imprima 7 caracteres de substring

$ X = "Hello World"
$ echo $ x: 1: 7
Ello Wo

Substring do início da string, mas cortado nos últimos 2 caracteres

$ X = "Hello World"
$ echo $ x: 0: -2
Olá Wor

Obtenha um comprimento de string com esta versão da expansão dos parâmetros

$ X = "Hello World"
$ echo $ #x
11

Pesquise e substitua dentro de uma variável. Neste exemplo, substitua a primeira minúscula o por maiúsculas o

$ X = "Hello World"
$ echo $ x/o/o
Olá Mundo

Pesquise e substitua em uma variável, mas com todas as correspondências substituídas por causa da barra principal no padrão de pesquisa.

$ X = "Hello World"
$ echo $ x // o/o
Olá Mundo

Padrões começando com #, significa que a partida deve começar no início da string para ser substituída

$ X = "Hello World"
$ echo $ x/#h/j
Jello World

Exemplo em que a busca pela partida no início da string, mas falha porque a partida é posteriormente na string

$ X = "Hello World"
$ echo $ x/#w/j
Olá Mundo

Os padrões que começam com % corresponderão apenas ao final da string, como neste exemplo.

$ X = "Hello World"
$ echo $ x/%d/d hoje
Olá, mundo hoje

Exemplo para a partida final da string que falha porque a partida está no início da string.

$ X = "Hello World"
$ echo $ x/%h/Today
Olá Mundo

Use Shopt com Nocasematch para fazer substituição insensível de casos.

$ shopt -s nocasematch
$ X = "Hello World"
$ echo $ x/hello/Welcome
Welcome World

Desligue a Shopt com o NocaseMatch para fazer substituição sensível ao caso.

$ shopt -u nocasematch
$ X = "Hello World"
$ echo $ x/hello/Welcome
Olá Mundo

Procure variáveis ​​de ambiente que correspondam a um padrão.

$ My_a = 1
$ My_b = 2
$ My_c = 3
$ echo $ !MEU*
My_a my_b my_c

Obtenha uma lista de variáveis ​​correspondentes e depois passe por cada variável e imprima seu valor

$ My_a = 1
$ My_b = 2
$ My_c = 3
$ variáveis ​​= $ !MEU*
$ para i em $ variáveis; eco $ i; eco "$ !i "; feito
My_a
1
My_b
2
MEU C
3

Faça uma string toda maiúscula

$ X = "Hello World"
$ echo $ x ^^
OLÁ MUNDO
Faça uma corda toda minúscula
$ X = "Hello World"
$ echo $ x ,,
Olá Mundo
Faça o primeiro personagem de uma mancha de corda
$ X = "George Washington"
$ echo $ x^
George Washington
Faça o primeiro caractere de uma corda minúscula
$ X = bob
$ echo $ x,
prumo

Parâmetros posicionais

Os parâmetros posicionais são normalmente pensados ​​como parâmetros da linha de comando, como usá -los são mostrados com exemplos abaixo.

Parâmetro $ 0 é o nome do script que está em execução e, em seguida, US $ 1, US $ 2, US $ 3 etc são parâmetros da linha de comando passados ​​para um script.

$ CAT Script.sh
eco $ 0
eco $ 1
eco $ 2
eco $ 3
$ bash ./roteiro.SH Apple Banana Cenout
./roteiro.sh
maçã
banana
cenoura

O parâmetro $* é uma única variável com todos os argumentos da linha de comando concatenados.

$ CAT Script.sh
eco $ 1
eco $ 2
eco $*
$ bash ./roteiro.sh Banana da maçã
maçã
banana
Banana da Apple

Parâmetro $# é um número com a quantidade de parâmetros posicionais passados ​​para um script neste caso abaixo, há 2 argumentos passados.

$ CAT Script.sh
eco $ 1
eco $ 2
eco $*
eco $#
$ bash ./roteiro.sh Banana da maçã
maçã
banana
Banana da Apple
2

Expansão Tilde

A expansão de Tilde é comumente vista com nomes de usuário e diretórios domésticos, os exemplos são mostrados abaixo.

Expansão Tilde para obter o diretório inicial do usuário atual, usando apenas tilde sem o nome de usuário.

$ eco $ usuário
raiz
$ CD ~/
$ PWD
/raiz

Consulte o diretório inicial de um usuário específico, não o usuário atual com Tilde e o nome de usuário

$ CD ~ Linuxhint
$ PWD
/home/linuxhint

Substituição aritmética

A substituição aritmética permite que o Bash faça operações matemáticas no shell ou em um script. Exemplos de usos comuns são mostrados abaixo.

Substituição aritmética simples com $ e parênteses duplos

$ echo $ ((2 + 3))
5

O operador pós -incremento atualizará o valor por um após o comando atual, observe que há um decréscimo pós equivalente não mostrado aqui.

$ X = 2
$ echo $ ((x ++))
2
$ echo $ x
3

O operador de pré -incremento atualizará o valor em um pouco antes do comando atual, observe que há um operador equivalente de pré -decrementos não mostrado aqui.

$ X = 2
$ echo $ ((++ x))
3
$ echo $ x
3

O operador de expoente pode aumentar um número para uma energia exponencialmente

$ echo $ ((5 ** 2))
25

Deslocamento para a esquerda; Nesse caso, mude os bits do número decimal 8 para a esquerda, que essencialmente o multiplica por 2

$ echo $ ((8<<1))
16

Mudança direita à direita; Nesse caso, mude os bits do número decimal 8 para a direita que divide essencialmente o número por 2

$ echo $ ((8 >> 1))
4

Bitwee.

$ echo $ ((4 e 5))
4

Bitwise ou operador comparará os números pouco a pouco e os resultados serão os bits onde qualquer uma das entradas tem o conjunto.

$ echo $ ((4 | 9))
13

O operador de igualdade aritmética testará a verdade e retornará 1 ou 0

$ echo $ ((4 == 4))
1

O operador de desigualdade aritmética testará a não igualdade e retornará 1 ou 0

$ echo $ ((4 != 4))
0

O operador condicional testará o primeiro argumento se verdadeiro, substitua pelo segundo argumento e se false substituir pelo terceiro. Nesse caso, 5 é igual a 4+1, então o primeiro condicional é verdadeiro e 9 é retornado. 5 não é igual a 4+2, então no segundo eco 7 é devolvido.

$ echo $ ((5 == 4+1 ? 9: 7))
9
$ echo $ ((5 == 4+2 ? 9: 7))
7

Você pode usar números hexadecimais em expansões aritméticas, neste caso 0XA é equivalente a 10 e 10+7 = 17.

$ echo $ ((0xa + 7))
17

Divisão de palavras

Usando a variável de ambiente IFS para registrar um delimitador e, usando os comandos de leitura e readArray, podemos analisar strings em uma variedade de tokens e depois contar os tokens e operar neles. Exemplos são mostrados abaixo.
Use o parâmetro IFS como delimitador, leia os tokens em uma matriz dividida por ifs que é definido como um personagem espacial e depois imprima os tokens um por um

$ text = "Hello World"
$ Ifs = "
$ leia -um tokens <<< "$text"
$ echo "Existem $ #tokens [*] palavras no texto."

Existem 2 palavras no texto.

$ para i em "$ tokens [@]"; eco $ i; feito
Olá
Mundo

Usuário readArray sem ifs e especifique o delimitador no comando readArray. Observe que este é apenas um exemplo em que dividimos um caminho de diretório com base no delimitador de barra. Nesse caso, o código incluiu a string vazia antes da primeira barra, que precisaria ser ajustada em um uso real, mas estamos apenas mostrando como chamar o ReadArray para dividir uma string em tokens em uma matriz com um delimitador.

$ path = "/home/linuxhint/usr/local/bin"
$ readarray -d / -t tokens <<< "$path"
eco "Existem $ #tokens [*] palavras no texto."

Existem 6 palavras no texto.

$ para i em "$ tokens [@]"; eco $ i; feito
lar
Linuxhint
USR
local
BIN

Expansão do nome do arquivo

Ao desejar se referir a uma lista de arquivos ou diretórios no sistema de arquivos, um comando Bash ou script bash pode usar a expansão do nome do arquivo para gerar uma lista de arquivos e diretórios de comandos simples. Exemplos são mostrados abaixo.

O caractere * se expande para um curinga e pega todos os arquivos correspondentes com o restante da sequência de curinga. Aqui pegamos todos os arquivos que terminam em .txt e passe -os para o comando DU para verificar o tamanho do disco.

$ toque a.txt b.txt c.TXT
$ eco "Hello World"> Conteúdo.TXT
$ du *.TXT
0 a.TXT
0 b.TXT
0 c.TXT
4 conteúdo.TXT

O ? O personagem corresponderá apenas a um único caractere, não um número infinito de caracteres e, portanto, neste exemplo, apenas capturará nomes de arquivos com um único caractere seguido por .TXT.

$ toque a.txt b.txt c.TXT
$ eco "Hello World"> Conteúdo.TXT
$ du ?.TXT
0 a.TXT
0 b.TXT
0 c.TXT

Personagens entre colchetes se expandem para combinar com qualquer um dos personagens. Neste exemplo, um.txt e c.txt são captados pela expansão

$ toque a.txt b.txt c.TXT
$ eco "Hello World"> Conteúdo.TXT
$ du [AC].TXT
0 a.TXT
0 c.TXT

Personagens entre colchetes podem ser uma variedade de caracteres e vemos aqui todos os arquivos de A a C, seguidos por .o sufixo txt é recolhido

$ toque a.txt b.txt c.TXT
$ eco "Hello World"> Conteúdo.TXT
$ du [a-c].TXT
0 a.TXT
0 b.TXT
0 c.TXT

Conclusão

Cobrimos muitos tipos de expansões de conchas neste artigo e espero que os exemplos simples possam servir como um livro de receitas para o que é possível em Bash para torná -lo mais produtivo com expansões de concha. Como referências adicionais, recomendo ler o manual completo do Bash, e também os muitos bons artigos no site da Nixcraft sobre scripts de bash, incluindo expansões de shell. Temos outros artigos que podem ser do seu interesse no Linuxhint, incluindo: 30 exemplos de scripts de bash, cordas em minúsculas em minúsculas, correspondência de padrões de batida e exemplos de cordas divididas em divisão. Além disso, temos um curso popular de 3 horas gratuito sobre programação Bash que você pode encontrar no YouTube.