Como eu uso $ * ao omitir certas variáveis de entrada como $ 1 e $ 2 no script bash?

14

Por exemplo,

elif [[ $append = $1 ]]
then
  touch ~/directory/"$2".txt
  echo "$variable_in_question" >> ~/directory/"$2".txt

para criar um arquivo de texto contendo todas as entradas seguindo "$2" ou anexar um arquivo de texto existente com todas as entradas após "$2" , o que eu usaria no lugar do "$variable_in_question" na linha 4?

Eu basicamente quero "$*" , mas omitindo "$1" e "$2" .

    
por Oreoplasm 03.03.2018 / 20:54

3 respostas

31

Você pode usar bash Parameter Expansion para especificar um faixa, isso também funciona com os parâmetros posicionais. Para $3$n , seria:

"${@:3}" # expands to "$3" "$4" "$5" …
"${*:3}" # expands to "$3 $4 $5 …"

Esteja ciente de que $@ e $* ignoram o primeiro argumento $0 . Se você quer saber qual deles usar no seu caso: é muito provavelmente que você queira uma cotação $@ . Não use $* , a menos que você explicitamente não queira que os argumentos sejam citados individualmente.

Você pode experimentar da seguinte forma:

$ bash -c 'echo "${@:3}"' 0 1 2 3 4 5 6
3 4 5 6
$ echo 'echo "${@:3}"' >script_file
$ bash script_file 0 1 2 3 4 5 6
2 3 4 5 6

No primeiro exemplo, $0 é preenchido com o primeiro argumento 0 , enquanto, quando usado em um script, $0 é preenchido com o nome do script, como mostra o segundo exemplo. O nome do script para bash , claro, é o primeiro argumento, só que normalmente não é percebido como tal - o mesmo vale para um script feito executável e chamado "diretamente". Portanto, no primeiro exemplo, temos $0 = 0 , $1 = 1 etc., enquanto na segunda é $0 = script_file , $1 = 0 , $2 = 1 etc .; ${@:3} seleciona todos os argumentos que começam com $3 .

Alguns exemplos adicionais para intervalos possíveis:

 # two arguments starting with the third
$ bash -c 'echo "${@:3:2}"' 0 1 2 3 4 5 6
3 4
 # every argument starting with the second to last one
 # a negative value needs either a preceding space or parentheses
$ bash -c 'echo "${@: -2}"' 0 1 2 3 4 5 6
5 6
 # two arguments starting with the fifth to last one
$ bash -c 'echo "${@:(-5):2}"' 0 1 2 3 4 5 6
2 3

Leitura adicional:

por dessert 04.03.2018 / 00:05
27

Você pode usar o shift builtin:

$ help shift
shift: shift [n]
    Shift positional parameters.

    Rename the positional parameters $N+1,$N+2 ... to $1,$2 ...  If N is
    not given, it is assumed to be 1.

    Exit Status:
    Returns success unless N is negative or greater than $#.

dado

$ cat argtest.bash 
#!/bin/bash

shift 2

echo "$*"

então

$ ./argtest.bash foo bar baz bam boo
baz bam boo
    
por steeldriver 03.03.2018 / 21:02
13

Geralmente, você pode copiar os parâmetros posicionais para uma matriz, excluir índices arbitrários da matriz e, em seguida, usar a matriz para expandir exatamente os índices desejados, sem perder seus argumentos originais.

Por exemplo, se eu quisesse todos os argumentos, exceto o primeiro, quarto e quinto:

args=( "$@" )
unset args[0] args[3] args[4]
echo "${args[@]}"

Na cópia, os índices são deslocados por 1, pois $0 não faz parte de $@ .

    
por muru 04.03.2018 / 04:33