bash - type -a가 "$(printf 'a')"를 수행하는 이유는 무엇이며 원래 별칭을 되돌릴 수 있습니까? [복사]

bash - type -a가 "$(printf 'a')"를 수행하는 이유는 무엇이며 원래 별칭을 되돌릴 수 있습니까? [복사]

내가 이걸 물어본 후질문이틀 전에 나는 ~/.bashrc에 다음 별칭을 만들기로 결정했습니다.

별칭 ​​catvu="LC_ALL=C sed \"$(printf 's/[^\t -\176\200-\377]/^&/g')\"|LC_ALL=C tr '\0-\ 10\ 13-\37\177''@-HK-_?'"

별칭을 grep하면 출력이 정확합니다.

[xiaobai@xiaobai note]$ grep catvu ~/.bashrc
alias catvu="LC_ALL=C sed \"$(printf 's/[^\t -\176\200-\377]/^&/g')\"|LC_ALL=C tr '\0-\10\13-\37\177' '@-HK-_?'"

그러나 출력은 약간 다르며 printf가 사라집니다.

[xiaobai@xiaobai note]$ type -a catvu
catvu is aliased to `LC_ALL=C sed "s/[^  -~�-�]/^&/g"|LC_ALL=C tr '\0-\10\13-\37\177' '@-HK-_?''

나는 시도했다고양이-V:

[xiaobai@xiaobai note]$ type -a catvu | cat -v
catvu is aliased to `LC_ALL=C sed "s/[^  -~M-^@-M-^?]/^&/g"|LC_ALL=C tr '\0-\10\13-\37\177' '@-HK-_?''

그리고헥스덤프-C:

[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 '\0-\10\13-\37|                                                                        
00000050  5c 31 37 37 27 20 27 40  2d 48 4b 2d 5f 3f 27 27  |\177' '@-HK-_?''|                                                                        
00000060  0a                                                |.|                                                                                       
00000061                                                                                                                                              
[xiaobai@xiaobai note]$ 

나는 그것을 다음과 같이 좁혔습니다.

alias catvu2="$(printf 'a')"

출력은 다음과 같습니다.

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

어느명령은 동일합니다.

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

그래서 내 질문은 왜$(인쇄 기능실행되었습니다. 어떻게 얻을 수 있나요?원래 원시 문자열사용하여A형주문하다?

답변1

명령 대체는 $(printf ....)큰따옴표 안에 있습니다.

alias catvu="LC_ALL=C sed \"$(printf 's/[^\t -\176\200-\377]/^&/g')\"|LC_ALL=C tr '\0-\10\13-\37\177' '@-HK-_?'"

$(printf ....)따라서 명령 대체를 실행하십시오.앞으로별칭은 다음과 같습니다.한정된.

동일한 점을 설명하기 위해 더 간단한 예를 들어 보겠습니다. 쉘 변수를 정의해 봅시다 d:

$ d="a b $(printf "%s" hello) c d"

이제 어떻게 정의되는지 declare -p살펴보겠습니다 .d

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

다시 말하지만, 별칭과 마찬가지로 명령 대체는 쉘 변수가 정의되기 전에 먼저 수행됩니다.

지연된 실행printf

고려하다:

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

위의 내용 $(printf ...)은 작은따옴표 안에 있습니다. 따라서 명령은 다음으로 대체됩니다.아니요실행되고 printf명령문은 별칭 정의의 일부입니다.

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

printf그러나 별칭을 실행하면 다음이 실행됩니다.

$ abc
a b Hello c d

답변2

다음 두 명령을 시도하고 결과를 확인하십시오.

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

기본적으로 작은따옴표는 "원래 원시 문자열"을 제공하는 반면 큰따옴표 안의 모든 내용은 별칭에 할당되기 전에 평가됩니다.

그러나 두 번째 명령의 출력에는 "a" 주위의 작은따옴표가 누락되어 있음을 알 수 있습니다. 따옴표 손실을 방지하려면 따옴표를 다시 확인하고 추적해야 합니다. \"작은 따옴표 안에는 사용할 수 없다는 점을 제외하면 안쪽 큰 따옴표를 사용해야 하는 것과 같습니다. 당신은 그런 것을 사용해야합니다 '\''.

따라서 별칭 대신 함수를 사용하여 따옴표로 인해 보호받는 것에 대해 걱정할 필요가 없도록 권장합니다. 또한 명령줄에서 파일 이름을 지정할 수 있으며 별칭은 파일에 무언가를 파이프하는 경우에만 작동합니다.

catvu () {
    LC_ALL=C sed "$(printf 's/[^\t -\176\200-\377]/^&/g')" "$@" | LC_ALL=C tr '\0-\10\13-\37\177' '@-HK-_?'
}

관련 정보