Por que o -a em “#! / bin / sh -a” afeta sed e “set -a” não afeta?

20

Se eu executar o seguinte arquivo .sh:

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

O resultado é um erro:

sed: -e expression #1, char 18: Invalid range end

Mas, se eu executar o seguinte arquivo .sh:

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

Ele é executado sem erro. O segundo código não é equivalente ao primeiro? Por que o erro no primeiro?

    
por Rodrigo 13.08.2018 / 17:40

1 resposta

31

Quando o bash é chamado com o nome sh , ele faz isso :

if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '
if (act_like_sh)
  {
    bind_variable ("POSIXLY_CORRECT", "y", 0);
    sv_strict_posix ("POSIXLY_CORRECT");
  }
') act_like_sh++;

e depois define o shell POSIXLY_CORRECT variável para y :

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

bind_variable chamadas bind_variable_internal , que, se o atributo de shell a estiver ativado no momento (o que seria se você invocasse o shell com -a ), favor a variável shell como exportada .

Então, no seu primeiro roteiro:

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

sed é invocado com POSIXLY_CORRECT=y em seu ambiente, o que fará com que ele se queixe de [\d001-\d008] . (A mesma coisa acontece se o sed receber a opção --posix .)

No GNU sed, \dNNN é um código de escape para o caractere cujo valor numérico na base 10 é NNN , mas no modo POSIX, isso é desativado dentro de uma expressão de colchetes, portanto [\d001-\d008] , significa literalmente os caracteres \ , d , etc., com o intervalo sendo de 1 a \ . Na ordem dos códigos de caracteres, 1 vem antes de \ (e o intervalo inclui todos os dígitos, exceto zero, além de todas as letras maiúsculas, além de alguns caracteres especiais). No en_US.UTF-8 locale que você estava usando, \ ordena antes de 1 , mas o intervalo é inválido.

No seu segundo script:

if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '
if (act_like_sh)
  {
    bind_variable ("POSIXLY_CORRECT", "y", 0);
    sv_strict_posix ("POSIXLY_CORRECT");
  }
') act_like_sh++;

mesmo que POSIXLY_CORRECT esteja definido no shell, ele não é exportado, portanto, o sed é invocado sem POSIXLY_CORRECT no ambiente e o sed é executado com as extensões do GNU.

Se você adicionar export POSIXLY_CORRECT próximo ao topo do seu segundo script, você também verá a reclamação de sed.

    
por 13.08.2018 / 21:18