Passando um argumento de linha de comando bash contendo um ponto

6

Como um argumento de linha de comando contendo um ponto (.) pode ser passado? Há alguma seqüência de escape para capturar caracteres como ponto?

A seguinte invocação de um script bash do shell não funciona:

# ./deploy.sh input.txt
./deploy.sh: line 9: input.txt: syntax error in expression (error token is ".txt")

Eu tentei o seguinte:

  1. barra invertida
  2. orçamento
  3. aspas duplas
  4. ./ deploy.sh input (isso funciona)

EDITAR

Use este caso de uso:

  1. Eu tenho 3 arquivos: server.jar client.jar gui.jar
  2. Eu preciso scp-los de uma fonte para um dest
  3. diretório de origem: login1 @ host1: / home / xyz / deploy /
  4. dir dest: login2 @ host2: / dados / apps / env / software / binário /

Solução:

  1. Ler artefatos a serem copiados em uma matriz a partir da linha de comando
  2. crie strings de caminho de destino e caminho de origem usando os prefixos de diretório corretos
  3. use um loop for para scp cada artefato (tendo descoberto os caminhos)

Aqui está o script simples que está fazendo 1 (leia artefatos em uma matriz):

#!/bin/bash
declare -a artifacts
for i
do
artifacts[i]=$i
echo ${artifacts[i]}
done

Execução1

-bash-3.00$ ./simple.sh arg1 arg2 arg3
arg1
arg2
arg3

Execução2

-bash-3.00$ ./simple.sh arg1.txt arg2.txt arg3.txt
./simple.sh: line 7: arg1.txt: syntax error in expression (error token is ".txt")
    
por user640378 11.05.2012 / 16:26

2 respostas

9

Você precisa usar declare -A em vez de declare -a . Você está claramente usando matrizes associativas com argumentos de cadeia arbitrários como índices, mas declare -a é somente para matrizes indexadas inteiras. arg.txt não avalia para um inteiro válido, daí o seu erro.

Editar

Parece que você está usando bash versão 3. Infelizmente, as matrizes associativas não estão disponíveis até a versão 4. Recomendo que você publique uma versão higienizada do script deploy.sh original com informações pessoais confidenciais removidas para que você possa obter ideias outras pessoas sobre abordagens alternativas.

Editar 2

Só para resumir um pouco de troca no bate-papo:

A maneira mais fácil de executar alguma ação sobre todos os argumentos é apenas iterar sobre eles com um for loop:

    for arg; do
        scp login1@host1:"$arg" login2@host2:/dest/
    done

Lembre-se de aspas duplas de todas as instâncias de "$arg" . Você não precisa colocar os argumentos em um array sozinho, pois eles já existem no array $@ , que é o que o for usa por padrão quando você não dá um% co_de explícito %.

    
por 11.05.2012 / 16:51
5

Esse erro acontece sempre que você tenta usar uma string onde um número era esperado.

Por exemplo

$((input.txt))

fará com que o mesmo erro seja impresso.

No seu caso, você está atribuindo a uma matriz que usa um índice numérico.

jw013 com razão explica você precisa fazer declare -A (maiúscula A) para o seu exemplo funcionar.

O motivo:

Ao atribuir a um elemento de matriz, você normalmente escreveria

array[0]=foo
array[1]=bar

mas você também pode escrever qualquer expressão aritmética como a chave, por exemplo

array[0+0]=foo
array[1+0]=bar

então o shell está vendo

array[input.txt]=input.txt

tentando convertê-lo em um número como

$((input.txt))

e falhando.

A razão pela qual o ponto é confuso e que os argumentos sem ponto parecem funcionar é

$((input))

é na verdade um número válido.

bashinput , decide que é um nome de variável válido, vê que a variável não está definida e a substitui por 0 .

Compare isso com input.txt , que não é um nome de variável válido, porque os nomes das variáveis não podem conter pontos!

Para evitar esse comportamento confuso, você pode usar

set -u

em seguida, sempre que você tentar usar uma variável que não existe, você receberá um erro, por exemplo,

set -u
artifacts[arg1]=arg1

imprime o erro

scriptname: line number: arg1: unbound variable
    
por 11.05.2012 / 16:45