confused sobre variáveis no bash

0

Eu sei que as variáveis no bash não têm nenhum tipo, mas estou confuso sobre o valor atribuído a elas.

O seguinte script simples funciona bem no bash

#!/bin/bash 
tail -n +2 /cygdrive/c/workdir\ \(newco\,\ LLC\)/workfile.txt > \
/cygdrive/c/workdir\ \(newco\,\ LLC\)/workfile2.txt

No entanto, o seguinte não

#!/bin/bash
tmpdir=/cygdrive/c/workdir\ \(newco\,\ LLC\)
tail -n +2 $tmpdir/workfile.txt > $tmpdir/workfile2.txt

Existe uma explicação para esse comportamento?

    
por gappy 05.06.2014 / 22:54

2 respostas

3

Você deve certificar-se de citar variáveis que podem ter espaços nelas. No seu caso, tail está recebendo três arquivos: /cygdrive/c/workdir , (newco, e LLC) porque $tmpdir tem três palavras separadas por espaços.

Eu sei que você escapou do espaço ao atribuir $tmpdir , mas isso apenas serviu para evitar que cada palavra fosse interpretada como um comando separado durante a atribuição. Se você, em seguida, echo $tmpdir , você receberá /cygdrive/c/workdir (newco, LLC) e que é o que está sendo passado para tail .

Para evitar isso, cite $tmpdir :

tail -n +2 "${tmpdir}/workfile.txt" > "${tmpdir}/workfile2.txt"
    
por 05.06.2014 / 22:59
0

Digite a primeira linha no bash e, em seguida, repita essa variável. É isso que você verá:

$ tmpdir=/cygdrive/c/workdir\ \(newco\,\ LLC\)
$ echo $tmpdir
/cygdrive/c/workdir (newco, LLC)

Se ainda não está claro qual é o culpado, adicione echo no início de sua segunda linha e coloque-o entre aspas duplas. Você verá o comando que é realmente executado:

$ echo "tail -n +2 $tmpdir/workfile.txt > $tmpdir/workfile2.txt"
tail -n +2 /cygdrive/c/workdir (newco, LLC)/workfile.txt > /cygdrive/c/workdir (newco, LLC)/workfile2.txt

Você escapou adequadamente da atribuição de variáveis, mas isso não é suficiente. O Bash executa uma substituição de subcadeia simples, inserindo espaços adicionais e quebrando seu comando.

Como sugerido por @savanto em sua resposta, você pode agrupar variáveis entre aspas duplas para garantir que espaços extras não sejam tratados como separadores de argumentos. Esta linha:

tail -n +2 "${tmpdir}/workfile.txt" > "${tmpdir}/workfile2.txt"

ficará assim após a substituição da variável:

tail -n +2 "/cygdrive/c/workdir (newco, LLC)/workfile.txt" > "/cygdrive/c/workdir (newco, LLC)/workfile2.txt"

Esta é a maneira mais comum e preferida de resolver esse problema. Se você deseja desesperadamente evitar aspas duplas, pode tentar escapar em dobro: primeiro ao atribuir, depois da substituição.

$ tmpdir=/cygdrive/c/workdir\\ \\(newco\\,\\ LLC\\)
$ echo $tmpdir
/cygdrive/c/workdir\ \(newco\,\ LLC\)

Explicação rápida de barras invertidas triplas: uma barra invertida significa: "trate o próximo caractere como um caractere regular, ignore qualquer significado especial" (por exemplo, escape dele ). A primeira barra invertida é um caractere de escape, então o segundo será tratado como um caractere de barra invertida, e não um caractere de escape. Assim, a barra invertida dupla produz uma única barra invertida. O terceiro simplesmente escapa do seguinte caractere, como espaço ou parênteses. Por exemplo, a\\ b se tornará a\ b .

Agora, se substituirmos as variáveis em seu comando, ele será escapado corretamente:

tail -n +2 /cygdrive/c/workdir\ \(newco\,\ LLC\)/workfile.txt > /cygdrive/c/workdir\ \(newco\,\ LLC\)/workfile2.txt
    
por 05.06.2014 / 23:23

Tags