Backslash na substituição de variáveis no Bash

4

Eu estava trabalhando em um script Bash para ajudar a particionar um disco rígido corretamente, e me deparei com um problema estranho em que eu tinha que acrescentar um número a uma variável. Levei um tempo para acertar o resultado, já que não sou muito experiente com Bash, mas consegui fazer algo temporário.

Aqui está um exemplo do que eu estava construindo:

#!/bin/bash

devName="/dev/sda"
devTarget=$devName

echo "$devTarget"

A variável devName foi /dev/sda , mas também precisei de um conjunto de variáveis para a terceira partição mais tarde no script, então usei o símbolo \ , que me permite adicionar o número 3 à /dev/sda para fazer a saída /dev/sda3

Mesmo que o símbolo \ tenha funcionado, só queria saber se esse é o jeito certo de fazer algo assim. Eu usei isso porque em Python é usado para ignorar o seguinte caractere para citações e tal, mas eu queria fazer o oposto nesta situação, então surpreendentemente funcionou. Se esta não é a melhor maneira de adicionar variáveis, alguém poderia mostrar um exemplo da melhor maneira de fazer isso no Bash.

    
por Tomasz 20.01.2018 / 07:17

4 respostas

7

A maneira segura de interpolar uma variável em uma string é usar ${var_name} . Por exemplo:

#!/bin/bash

devName="/dev/sda"
devTarget="${devName}3"

echo "$devTarget"

Desta forma, Bash não tem dúvidas sobre qual é a variável a interpolar.

Btw, interessante como funciona devTarget=$devName . Não sei porquê.

    
por 20.01.2018 / 07:28
5

$x\b funciona da mesma forma que $x"b" ou "$x"b funcionam, as aspas terminam o nome da variável. Se por nenhum outro motivo, eu acho que isso acontece porque as citações ainda estão lá quando a variável é expandida e nenhuma de \"' é válida em nomes de variáveis.

O texto padrão diz que:

The order of word expansion shall be as follows:

1. ..., parameter expansion (see Parameter Expansion), ...

4. Quote removal (see Quote Removal) shall always be performed last.

E "remoção de cotação" é a etapa que realmente remove os caracteres de cotação.

Mas, como @tomasz declarou em sua resposta , colocar chaves ao redor do nome da variável é a maneira usual de faça isso, então "${x}b" ou "${devName}3" . Você quase sempre quer colocar as cotações em torno de uma expansão, veja Quando é necessário fazer uma cotação dupla?

(Embora eu tenha me perguntado se poderia haver outras maneiras de marcar uma string entre aspas dentro de um programa, além de deixar os caracteres de aspas no lugar).

    
por 20.01.2018 / 08:34
3

O que seu script mostra é que você está escrevendo a variável mais o número para a saída. Fácil o suficiente para ser alcançado com printf e string formatada:

$ devName="/dev/sda"
$ printf "%s%d\n" "$devName" 3
/dev/sda3

Mas, como você mencionou que precisa usar uma nova variável posteriormente no script, também podemos usar -v flag na versão de bash de printf

$ printf -v devTarget "%s%d" "$devName" 3
$ echo "$devTarget"
/dev/sda3

Essa abordagem não funciona com POSIX printf e não funciona em outros shells (pelo menos ksh e mksh não tem -v flag para printf, não tenho certeza sobre zhsh). Então, poderíamos contornar isso via substituição de comando:

$ devTarget=$(printf "%s3" "$devName")

No entanto, a resposta aceita provavelmente seria mais simples e mais portátil.

    
por 20.01.2018 / 13:54
1

Como tomasz apontou , a maneira correta de especificar exatamente quais caracteres constituem o nome da variável é usar chaves , como ${devName}3 .

O Bash permite omitir as chaves como uma conveniência, mas ao fazê-lo, você perde a capacidade de ser totalmente explícito sobre qual variável deseja referenciar. A maneira como o bash resolve isso é pegando o nome de variável válido mais longo possível que inicia após o cifrão. Os nomes de variáveis começam com uma letra ou sublinhado e podem conter qualquer número de letras, números ou sublinhados, mas nenhum outro caractere. Portanto, no seu exemplo, $devName , bash começa com d e procura a execução mais longa dos caracteres de letra / número / sublinhado que pode encontrar, que é devName . É preciso que seja o nome da variável a ser usada. Da mesma forma, algo como $here-is-a-long-string-of-words usaria a variável chamada here ; seria como ${here}-is-a-long-string-of-words .

Depois disso, o bash verá . A contrabarra é uma forma de citar, no sentido de que faz com que o caractere seguinte seja interpretado normalmente, sem qualquer significado especial. Mas 3 não tem nenhum significado especial, então a contrabarra é redundante. Essa sequência acaba sendo equivalente a apenas 3 por si só.

    
por 22.01.2018 / 07:37