Como o comentário de Cachinhos Dourados e as referências da humanidade descrevem,
shift reatribui os parâmetros posicionais ( $1 , $2 , etc.)
para que $1 assuma o valor antigo de $2 ,
$2 assume o valor de $3 , etc. *
O valor antigo de $1 é descartado. ( $0 não é alterado.)
Algumas razões para isso incluem:
- Permite acessar o décimo argumento (se houver) mais facilmente.
$10 não funciona - é interpretado como $1 concatenado com 0
(e assim pode produzir algo como Hello0 ).
Depois de um shift , o décimo argumento se torna $9 .
(No entanto, na maioria dos shells modernos, você pode usar ${10} .)
- Como o Guia do Bash para iniciantes demonstra,
ele pode ser usado para percorrer os argumentos.
IMNSHO, isso é desajeitado;
for é muito melhor para isso.
- Como no seu script de exemplo,
torna fácil processar todos os argumentos da mesma maneira, exceto alguns.
Por exemplo, no seu script,
$1 e $2 são cadeias de texto,
enquanto $3 e todos os outros parâmetros são nomes de arquivo.
Então, veja como isso acontece.
Suponha que seu script seja chamado de Patryk_script e seja chamado de
Patryk_script USSR Russia Treaty1 Atlas2 Pravda3
O script vê
$1 = USSR
$2 = Russia
$3 = Treaty1
$4 = Atlas2
$5 = Pravda3
A instrução ostr="$1" define a variável ostr para USSR .
A primeira instrução shift altera os parâmetros posicionais da seguinte forma:
$1 = Russia
$2 = Treaty1
$3 = Atlas2
$4 = Pravda3
A instrução nstr="$1" define a variável nstr para Russia .
A segunda instrução shift altera os parâmetros posicionais da seguinte forma:
$1 = Treaty1
$2 = Atlas2
$3 = Pravda3
Em seguida, o loop for altera USSR ( $ostr ) para Russia ( $nstr )
nos arquivos Treaty1 , Atlas2 e Pravda3 .
Existem alguns problemas com o script.
-
for file in $@; do
Se o script for invocado como
Patryk_script USSR Russia Treaty1 "World Atlas2" Pravda3
ele vê
$1 = USSR
$2 = Russia
$3 = Treaty1
$4 = World Atlas2
$5 = Pravda3
mas, como $@ não é citado, o espaço em World Atlas2 não é citado,
e o loop for acha que tem quatro arquivos: Treaty1 , World , Atlas2 ,
e Pravda3 .
Isso deve ser
for file in "$@"; do
(para citar qualquer caractere especial nos argumentos) ou simplesmente
for file do
(que é equivalente à versão mais longa).
-
eval "sed 's/"$ostr"/"$nstr"/g' $file"
Não é necessário que este seja um eval ,
e passar a entrada do usuário desmarcada para um eval pode ser perigoso.
Por exemplo, se o script for invocado como
Patryk_script "'; rm *;'" Russia Treaty1 Atlas2 Pravda3
executará rm * !
Esta é uma grande preocupação se o script puder ser executado
com privilégios superiores aos do usuário que a invoca;
por exemplo, se puder ser executado por meio de sudo ou invocado em uma interface da web.
Provavelmente não é tão importante se você usá-lo como você mesmo,
no seu diretório.
Mas isso pode ser alterado para
sed "s/$ostr/$nstr/g" "$file"
Isso ainda apresenta alguns riscos, mas eles são muito menos graves.
-
if [ -f $file ] , > $file.tmp e mv $file.tmp $file
deve ser if [ -f "$file" ] , > "$file.tmp" e mv "$file.tmp" "$file" ,
respectivamente, para manipular nomes de arquivos
que pode ter espaços (ou outros personagens engraçados) neles.
(O comando eval "sed … também manipula nomes de arquivos que possuem espaços neles.)
* shift aceita um argumento opcional:
um inteiro positivo que especifica quantos parâmetros para mudar.
O padrão é um ( 1 ).
Por exemplo, shift 4 causa $5
para se tornar $1 ,
$6 para se tornar $2 e assim por diante.
(Observe que o exemplo no Guia do Bash para iniciantes está errado.)
E assim o seu script pode ser modificado para dizer
ostr="$1"
nstr="$2"
shift 2
que pode ser considerado mais claro.
Nota final / Aviso:
O idioma do Prompt de Comando do Windows (arquivo de lote)
também suporta um comando SHIFT ,
que faz basicamente a mesma coisa que o comando shift em shells Unix,
com uma diferença marcante,
que eu vou esconder para evitar que as pessoas fiquem confusas com isso:
- A command like
SHIFT 4 is an error,
yielding an “Invalid parameter to SHIFT command” error message.
-
SHIFT /n, where n is an integer between 0 and 8,
is valid — but it doesn’t shift n times.
It shifts once, starting with the n th argument.
So SHIFT /4 causes %5 (the fifth argument) to become %4,
%6 to become %5, and so on, leaving arguments 0 through 3 alone.