cant não expandirá minha variável BASH no script

1

Eu tenho esse script, que irá solicitar o caminho relativo ou absoluto para o arquivo e, em seguida, trocar espaços em branco '' com '\' que funciona no console do Linux. A substituição é feita usando o primeiro comando sed . Após a substituição eu echo o caminho apenas para verificação e está correto.

Depois vem o segundo comando sed que tem que lidar com o arquivo para o qual eu escrevi o caminho absoluto. Bem, não vai funcionar ... Parece que no segundo comando $ drill_file não está se expandindo. O mais estranho é que ele se expande muito bem fora do script ... WOOT!?

#!/bin/bash

echo "Give relative or absolute path to the \"drill.TXT\" file:"

read drill_file_temp
drill_file=$(echo $drill_file_temp | sed -r 's/\s/\ /g')
echo $drill_file

sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]//' $drill_file

echo "Conversion finished."
    
por 71GA 06.02.2015 / 18:36

3 respostas

2

Você coloca caracteres em uma string. O problema é que os caracteres de cotação não são analisados após a expansão do parâmetro. Para obter o efeito desejado, você precisaria

eval sed ... $drill_file

Você pode usar set -x para ver como o shell vê a linha de comando:

> text=a\\ \\ \\ b
> echo $text
a\ \ \ b
> set -x
> : $text
+ : 'a\' '\' '\' b

Ou seja. o shell não vê um argumento, mas quatro.

Como disse aleady pelos outros: Você deve citar $drill_file / $drill_file_temp : "$drill_file"

    
por 06.02.2015 / 19:22
2

Você não precisa fazer o primeiro sed se você citar suas variáveis:

read -p "Give relative or absolute path to the \"drill.TXT\" file: " drill_file
if [[ -f "$drill_file" ]]; then
    sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]//' "$drill_file"
    echo "Conversion finished."
else
    echo "no such file: '$drill_file'"
fi
    
por 06.02.2015 / 19:11
0

o kernel não entende \ (barra invertida)
Se drill_file for 'file \ with \ space', sed será executado como% sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]//' file\ with\ space .
Primeiro, o shell clona-se e chama um membro da família execl de funções passando args com argv [0] = sed, argv [1] = s / (^ X [[: digit:]] ) [[: digit: ]] (Y [[: digit:]] ) [[: digit:]] / \ 1 \ 2 /, argv [2] = arquivo \, argv [3] = com \ e argv [4] = espaço. execl substitui shell por sed. Quando o sed começa a ser executado, ele chama open("file\ ",O_RDONLY) e faz o mesmo para 'with \' e 'space'. O kernel passa a solicitação para fs relevantes. Fs retorna ENOENT significando que não existe tal entrada no fs. Isso é verdade porque realmente não existem tais arquivos. sed recebe o erro e exibe a mensagem de erro.

se o arquivo $ drill_file tiver sido citado, o sed obterá o nome do arquivo como 'file \ with \ space' e também não abrirá essa vez.

eval sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]//' "$drill_file"
aqui eval analisa seus args e constrói comandos e executa o comando construído. É apenas redundante e complicado, você quebra e conserta.

\ (barra invertida) de escape só é aplicável quando o shell está sendo executado. sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]//' " $ drill_file_temp " teria sido bem-sucedido.
Isso também funciona.

sed 's/\(^X[[:digit:]]*\)[[:digit:]]\(Y[[:digit:]]*\)[[:digit:]]//' \
"$(read -p "Give relative or absolute path to the \"drill.TXT\" file: " \
drill_file_temp;echo $drill_file_temp)"
    
por 07.02.2015 / 18:29