bash - Por que o tipo -a executa “$ (printf 'a')” e é possível recuperar o alias original? [duplicado]

1

Depois que eu fizer essa pergunta 2 dias atrás, eu decidi fazer este apelido no meu ~ / .bashrc:

alias catvu="LC_ALL=C sed \"$(printf 's/[^\t -60-7]/^&/g')\"|LC_ALL=C tr '%bl0ck_qu0te%--7' '@-HK-_?'"

A saída está correta se eu consultar o alias pelo grep:

[xiaobai@xiaobai note]$ grep catvu ~/.bashrc
alias catvu="LC_ALL=C sed \"$(printf 's/[^\t -60-7]/^&/g')\"|LC_ALL=C tr '
[xiaobai@xiaobai note]$ type -a catvu
catvu is aliased to 'LC_ALL=C sed "s/[^  -~�-�]/^&/g"|LC_ALL=C tr '
[xiaobai@xiaobai note]$ type -a catvu | cat -v
catvu is aliased to 'LC_ALL=C sed "s/[^  -~M-^@-M-^?]/^&/g"|LC_ALL=C tr '
[xiaobai@xiaobai note]$ type -a catvu | hexdump -C                                                                                                    
00000000  63 61 74 76 75 20 69 73  20 61 6c 69 61 73 65 64  |catvu is aliased|                                                                        
00000010  20 74 6f 20 60 4c 43 5f  41 4c 4c 3d 43 20 73 65  | to 'LC_ALL=C se|                                                                        
00000020  64 20 22 73 2f 5b 5e 09  20 2d 7e 80 2d ff 5d 2f  |d "s/[^. -~.-.]/|                                                                        
00000030  5e 26 2f 67 22 7c 4c 43  5f 41 4c 4c 3d 43 20 74  |^&/g"|LC_ALL=C t|                                                                        
00000040  72 20 27 5c 30 2d 5c 31  30 5c 31 33 2d 5c 33 37  |r '
alias catvu2="$(printf 'a')"
--| 00000050 5c 31 37 37 27 20 27 40 2d 48 4b 2d 5f 3f 27 27 |7' '@-HK-_?''| 00000060 0a |.| 00000061 [xiaobai@xiaobai note]$
--7' '@-HK-_?''
--7' '@-HK-_?''
--7' '@-HK-_?'"

mas a saída é ligeiramente diferente na qual o printf desapareceu:

[xiaobai@xiaobai note]$ type -a catvu2
catvu2 is aliased to 'a'
[xiaobai@xiaobai note]$ 

eu tento com cat -v :

[xiaobai@xiaobai note]$ which catvu2
alias catvu2='a'
[xiaobai@xiaobai note]$ 

e hexdump -C :

[xiaobai@xiaobai note]$ grep catvu ~/.bashrc
alias catvu="LC_ALL=C sed \"$(printf 's/[^\t -60-7]/^&/g')\"|LC_ALL=C tr '
[xiaobai@xiaobai note]$ type -a catvu
catvu is aliased to 'LC_ALL=C sed "s/[^  -~�-�]/^&/g"|LC_ALL=C tr '
[xiaobai@xiaobai note]$ type -a catvu | cat -v
catvu is aliased to 'LC_ALL=C sed "s/[^  -~M-^@-M-^?]/^&/g"|LC_ALL=C tr '
[xiaobai@xiaobai note]$ type -a catvu | hexdump -C                                                                                                    
00000000  63 61 74 76 75 20 69 73  20 61 6c 69 61 73 65 64  |catvu is aliased|                                                                        
00000010  20 74 6f 20 60 4c 43 5f  41 4c 4c 3d 43 20 73 65  | to 'LC_ALL=C se|                                                                        
00000020  64 20 22 73 2f 5b 5e 09  20 2d 7e 80 2d ff 5d 2f  |d "s/[^. -~.-.]/|                                                                        
00000030  5e 26 2f 67 22 7c 4c 43  5f 41 4c 4c 3d 43 20 74  |^&/g"|LC_ALL=C t|                                                                        
00000040  72 20 27 5c 30 2d 5c 31  30 5c 31 33 2d 5c 33 37  |r '
alias catvu2="$(printf 'a')"
--| 00000050 5c 31 37 37 27 20 27 40 2d 48 4b 2d 5f 3f 27 27 |7' '@-HK-_?''| 00000060 0a |.| 00000061 [xiaobai@xiaobai note]$
--7' '@-HK-_?''
--7' '@-HK-_?''
--7' '@-HK-_?'"

eu diminuo:

[xiaobai@xiaobai note]$ type -a catvu2
catvu2 is aliased to 'a'
[xiaobai@xiaobai note]$ 

E a saída se torna:

[xiaobai@xiaobai note]$ which catvu2
alias catvu2='a'
[xiaobai@xiaobai note]$ 

qual comando é o mesmo:

%pre%

Então, minha pergunta é por que $ (printf é executado e como posso obter a seqüência original usando o comando type -a ?

    
por 林果皞 11.05.2015 / 06:46

2 respostas

2

Experimente os dois comandos seguintes e veja o que obtém:

echo "$(printf 'a')"
echo '$(printf 'a')'

Essencialmente, as aspas simples fornecem a sua "string original", enquanto que qualquer valor entre aspas duplas será avaliado antes de ser atribuído ao seu alias.

No entanto, você pode notar que as aspas simples em torno de 'a' estão faltando na saída do segundo comando. Você terá que seguir e rastrear suas citações cuidadosamente para evitar a queda de cotações - da mesma forma que você teve que usar \" para suas aspas duplas internas, exceto que você não pode fazer isso entre aspas simples. Você teria que usar algo como '\'' .

Por esse motivo, recomendo usar uma função em vez de um alias, para que você não precise se preocupar em proteger suas cotações. Isso também permite que você forneça um nome de arquivo na linha de comando, enquanto seu alias só funciona se você enviar algo para ele.

catvu () {
    LC_ALL=C sed "$(printf 's/[^\t -60-7]/^&/g')" "$@" | LC_ALL=C tr '
echo "$(printf 'a')"
echo '$(printf 'a')'
--7' '@-HK-_?' }
    
por 11.05.2015 / 07:12
3

Observe que a substituição de comandos $(printf ....) está dentro de aspas duplas:

alias catvu="LC_ALL=C sed \"$(printf 's/[^\t -60-7]/^&/g')\"|LC_ALL=C tr '
$ d="a b $(printf "%s" hello) c d"
--7' '@-HK-_?'"

Consequentemente, a substituição do comando $(printf ....) é executada antes do alias ser definido .

Vamos dar um exemplo mais simples que ilustra o mesmo ponto. Vamos definir uma variável de shell d :

$ declare -p d
declare -- d="a b hello c d"

Agora, vamos usar declare -p para ver exatamente como d foi definido:

$ alias abc='echo a b $(printf "%s" Hello) c d'

Novamente, assim como para o alias, a substituição do comando é executada primeiro, antes que a variável do shell seja definida.

Atrasando a execução de printf

Considere:

$ alias abc
alias abc='echo a b $(printf "%s" Hello) c d'

Acima, $(printf ...) está entre aspas simples. Consequentemente, a substituição do comando é não executada e a instrução printf faz parte da definição do alias:

$ abc
a b Hello c d

printf é, no entanto, executado quando executamos o alias:

alias catvu="LC_ALL=C sed \"$(printf 's/[^\t -60-7]/^&/g')\"|LC_ALL=C tr '
$ d="a b $(printf "%s" hello) c d"
--7' '@-HK-_?'"
    
por 11.05.2015 / 06:59