18 truques de string Bash que corrigem dores de cabeça comuns de script

por Nada Em Troca
9 minutos de leitura
18 truques de string Bash que corrigem dores de cabeça comuns de script

Você já olhou para um grande diretório de nomes de arquivos e temeu a ideia de renomear todos eles? Ou talvez seus scripts estejam repletos de instruções condicionais para verificar se existe uma variável de ambiente. Bash fornece uma sintaxe concisa para alterar strings que torna a vida mais fácil. Elas são chamadas de expansões de parâmetros e mostrarei como usá-las.

Em um nível básico, a expansão de parâmetros significa transformar a sintaxe do Bash em um valor – expandindo-o. Por exemplo:

echo "$foo"

Esta variável simples se transforma em seu valor atribuído. No entanto, é a forma menos útil de expansão de parâmetros e existem dezenas de outras que oferecem mais utilidade. Abordarei os mais importantes e apresentarei cenários do mundo real onde eles são eficazes. Conforme sua conveniência, você pode usá-los em scripts ou na linha de comando.

HTG embrulhado - 21 de dezembro
HTG Wrapped 2025: 24 dias de tecnologia

24 dias de nossos hardwares, gadgets e tecnologia favoritos

4
Por Will Verduzco

Mudança de caso

Você pode alterar a caixa de uma string inteira, ou parte dela, usando apenas o Bash.

O básico

Mude uma string inteira para maiúscula usando “^^”:

name="Hello, World!" echo "${name^^}"
Uma janela de terminal exibe o texto Hello World em letras maiúsculas.-2

Mude o primeiro caractere para maiúsculo usando “^”:

name="hello, World!" echo "${name^}"
Uma janela de terminal exibe o texto Hello World com a primeira letra maiúscula.

Altere toda a string para minúsculas usando “,,”:

name="HELLO, WORLD!" echo "${name,,}"
Uma janela de terminal exibe o texto Olá mundo em letras minúsculas.

Mude a primeira letra para minúscula usando “,”:

name="Hello, world!" echo "${name,}"
Uma janela de terminal exibe o texto Olá mundo com a primeira letra minúscula.-1

Exemplos do mundo real

Como usamos isso na prática?

Em um cenário, você pode encontrar muitos arquivos com nomes de arquivo em letras maiúsculas indesejáveis ​​(por exemplo, IMG_2025-01-01.jpg) e deseja renomeá-los em lote para letras minúsculas:

for file in IMG_*.jpg; do     mv "$file" "${file,,}" done

Isso também colocará em letras minúsculas as extensões de arquivo (abordadas posteriormente) e os caminhos (se incluídos).

Agora imagine um documento de texto cujos itens deveriam estar em letras maiúsculas. Por exemplo, uma lista de endereços MAC:

while read mac; do     echo "${mac^^}" done < mac_addresses.txt > mac_addresses_upper.txt

Às vezes, crio prompts para meus scripts avaliarem respostas sim ou não. É melhor converter a string antes da comparação em vez de escrever múltiplas cláusulas:

read -p "Continue? (Y/n): " answer if [[ "${answer^^}" == "N" ]]; then     echo "Stopping..."     exit 1 fi # This is yes!

Usando valores padrão

Encontrar variáveis ​​não definidas é comum durante a criação de scripts. Muitas vezes o seu script precisa fazer perguntas sobre valores antes de usá-los. Isso pode sobrecarregar seu código com declarações condicionais desagradáveis. Felizmente, o Bash tem uma maneira concisa de gerenciar esses cenários.

O básico

Se uma variável não estiver definida ou estiver vazia, você poderá retornar a um valor padrão com “:-“:

echo "${NAME:-value}"
Uma janela de terminal exibe o valor do texto.

Com um simples “-” (sem dois pontos), você pode voltar a um valor padrão se a variável nunca tiver sido declarada (não definida):

echo "${NAME-value}"
Uma janela de terminal exibe o valor do texto.-1

O operador “:+” é o oposto de “:-“: retroceda se “NAME” estiver definido e não vazio:

export NAME="foo" echo "${NAME:+value}"
Uma janela de terminal exibe o valor do texto.-2

Para “+”, “NAME” deve estar definido ou vazio antes de retornar ao valor padrão:

export NAME="foo" echo "${NAME+value}"
Uma janela de terminal exibe o valor do texto.-3

O operador “=” é um pouco diferente, pois faz duas coisas: define e retorna o valor. Para “:=”, o Bash faz isso se “NAME” não estiver definido ou estiver vazio:

                       # "NAME" is unset at this point. echo "${NAME:=value}"  # Expands to "value", but also sets "NAME" to "value". echo "$NAME"           # "NAME" is now set to "value"
Uma janela de terminal exibe o valor do texto duas vezes.

Quando excluímos os dois pontos (“=”), significa definir e retornar o valor quando “NOME” não for definido:

echo "${NAME=value}" echo "$NAME"
Uma janela de terminal exibe o valor do texto duas vezes.-1

Como essas regras são confusas, aqui está um resumo:

# Fallback to the default if "NAME"... echo "${NAME:-value}"  # Is unset or empty. echo "${NAME-value}"   # Is unset. echo "${NAME:+value}"  # Is set and not empty. echo "${NAME+value}"   # Is set or empty. echo "${NAME:=value}"  # Is unset or empty.   (Also, assign to "NAME.") echo "${NAME=value}"   # Is unset.            (Also, assign to "NAME.")

Exemplos do mundo real

A maneira sensata de localizar diretórios iniciais comuns é usar as constantes fornecidas pela especificação de diretório base XDG (também conhecida como XDG BDS), fornecida por freedesktop.org. No entanto, eles nem sempre estão definidos, então devemos voltar a um padrão sensato:

mv foo.conf "${XDG_CONFIG_HOME:-$HOME/.config}"

Talvez o seu script tenha operações de arquivo subsequentes e você não queira se repetir:

mv foo.conf "${XDG_CONFIG_HOME:=$HOME/.config}" # Also sets a value. mv bar.conf "$XDG_CONFIG_HOME" # We don't need to check.

Se ainda não estiver definido, isso atribuirá o valor XDG apropriado no primeiro uso.

Você pode até usar a expansão de parâmetros como uma condicional embutida e barata:

export DEBUG=true  # MUST "export" if executing in the CLI. echo "Running script${DEBUG:+ (debugging enabled)}..."  # Extra message, if debugging.

Isto imprimirá uma mensagem especial somente quando a depuração estiver ativa.

Alterando partes de uma string

Substituir parte de uma string é comum na linha de comando, e não apenas em scripts. Por exemplo, alteração em massa de nomes de arquivos ou manipulação de entrada do usuário. Freqüentemente usaríamos sed, mas o bash possui suporte integrado para correspondência de padrões que é mais conveniente e às vezes mais rápido.

O básico

Substituir a primeira ocorrência de uma string é simples usando “/”:

text="Hello, World!" echo "${text/World/Universe}"
Uma janela do terminal exibe o texto Olá, Universo!

Mas você pode substituir todos ocorrências usando “//”:

text="Hello, World! Hello, Universe!" echo "${text//Hello/Goodbye}"
Uma janela de terminal exibe o texto Adeus, mundo! Adeus, Universo!

Você pode até substituir o início de uma string (se corresponder) por “/#”:

text="Hello, World!" echo "${text/#Hello/Goodbye}"
Uma janela de terminal exibe o texto Adeus, mundo!

Ou você pode substituir o final de uma string correspondente usando “/%”:

text="Hello, World!" echo "${text/%World!/Universe!}"
Uma janela do terminal exibe o texto Olá, Universo!-1

Certifique-se de escapar dos caracteres especiais problemáticos (“!”), porque às vezes eles têm um significado especial e confundem o shell.

Você também pode remover partes de strings. O “#” removerá a instância correspondente mais curta:

file="foofoo.txt" echo "${file#foo}"
Uma janela de terminal exibe o texto foo.txt.

Vamos executar novamente o comando anterior incluindo um curinga para corresponder ao máximo possível da string:

file="foofoo.txt" echo "${file#foo*}"
Uma janela de terminal exibe o texto foo.txt.-1

Observe que os resultados são os mesmos? Isso porque “#” é preguiçoso e corresponderá o mínimo possível. Correspondeu a “foo” e depois desistiu. O curinga não teve efeito.

Por outro lado, usar “##” remove a correspondência mais longa possível (também conhecida como gananciosa):

file="foofoo.txt" echo "${file##foo*}"

Esse padrão correspondeu a toda a string, portanto não há saída.

Os operadores “%” e “%%” funcionam da mesma forma que “#” e “##”, exceto no sentido inverso. Em vez de trabalharem da esquerda para a direita, movem-se da direita para a esquerda.

O operador “%” remove a correspondência mais curta possível, da direita para a esquerda:

file="foo.bar.txt" echo "${file%.*}"
Uma janela de terminal exibe o texto foo.bar.

O padrão “.*” corresponderá a um ponto final e a qualquer coisa depois dele. Na string, notou que há dois pontos (três segmentos), mas apenas o segmento mais à direita foi correspondido?

Um “%%” remove a correspondência mais longa possível, da direita para a esquerda:

file="foo.bar.txt" echo "${file%%.*}"
Uma janela de terminal exibe o texto foo.

Esse é o mesmo padrão, exceto que usa “%%”. Ele se moveu da direita para a esquerda, correspondendo a “.*” conforme avançava. O segmento mais à esquerda não corresponde porque não começa com ponto final.

Esta também foi uma seção complicada, por isso merece uma folha de dicas:

echo "${var/pattern/value}"     # "/"   Replace the first occurrence. echo "${var//pattern/value}"    # "//"  Replace all occurrences. echo "${var/#pattern/value}"    # "/#"  Replace at the start. echo "${var/%pattern/value}"    # "/%"  Replace at the end. echo "${var#pattern}"           # "#"   Remove the shortest match (left to right). echo "${var##pattern}"          # "##"  Remove the longest match (left to right). echo "${var%pattern}"           # "%"   Remove the shortest match (right to left). echo "${var%%pattern}"          # "%%"  Remove the longest match (right to left).
Terminal Konsole aberto no laptop Kubuntu Focus Ir14 Linux.
Como obter uma folha de dicas para qualquer comando no terminal Linux

Às vezes, trapacear é necessário.

6
Por Zunaid Ali

Exemplos do mundo real

Imagine que você tem uma lista de arquivos e deseja alterar sua extensão:

for f in *.txt; do   mv "$f" "${f/%.txt/.md}" done

“%” substitui o final de uma string.

Sua câmera digital cria imagens com um prefixo irritante, então você deseja removê-las:

for f in IMG_*.jpg; do     mv "$f" "${f#IMG_}" done

“#” remove o início de uma string.

Talvez você tenha um caminho para um arquivo e queira apenas o nome do arquivo:

path="/home/user/documents/report.pdf" echo "${path##*/}"
Uma janela de terminal exibe o texto report.pdf.

“##” remove a correspondência mais longa, o que permite um curinga ganancioso, combinando até a última barra.

Talvez você queira apenas a extensão do arquivo:

filename="archive.tar.gz" echo "${filename##*.}"
Uma janela de terminal exibe o texto gz.

Por último, talvez você queira o nome base de um arquivo sem a extensão:

filename="document.tar.gz" echo "${filename%%.*}"
Uma janela de terminal exibe o documento de texto.

“%%” é ganancioso, da direita para a esquerda, parando no último segmento (esquerda).

Laptop com o terminal Linux aberto.
O arquivo Linux .bashrc: o que é, além de 6 coisas que você pode fazer com ele

O arquivo de controle de execução do Bash é muito legal e confiável.

Por Bobby Jack

Para mim, as expansões de parâmetros não são diferentes de um conceito geral de programação chamado expressões. Significa simplesmente transformar um trecho de código em um valor em tempo de execução. É um conceito valioso que pode melhorar seus scripts. Ele pode potencialmente minimizar o uso de instruções condicionais ou retardar desnecessariamente chamadas para ferramentas externas (como sed).

Você pode misturar e combinar expansões de parâmetros conforme necessário. Por exemplo, você pode incorporá-los:

echo "${FOO:-${BAR:-bar}}"

O padrão será “bar” se nem “FOO” nem “BAR” estiverem definidos. Tenha em mente que embora as declarações condicionais sejam feias, às vezes são mais fáceis de ler. Portanto, se você estiver aninhando profundamente expansões de parâmetros, repense sua abordagem e considere códigos “mais burros”, como instruções condicionais.

Mascote do Linux usando um laptop com alguns terminais multiplexadores ao redor.
8 funções essenciais do shell para melhorar sua linha de comando do Linux

Há uma função para todos.

11
Por Bobby Jack
Este artigo foi útil?
Gostei0Não Gostei0

Deixe um comentário

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?
-
00:00
00:00
Update Required Flash plugin
-
00:00
00:00