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-_?''
我嘗試使用cat -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-_?''
和hexdump -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]$
所以我的問題是為什麼要執行**$(printf以及如何使用type -a命令獲取原始原始字元串?**
嘗試以下兩個命令,看看你得到了什麼:
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-_?' }
請注意,命令替換
$(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 ....)
執行命令替換。讓我們舉一個更簡單的例子來說明同一點。讓我們定義一個 shell 變數
d
:$ d="a b $(printf "%s" hello) c d"
現在,讓我們
declare -p
來看看究竟是如何d
定義的:$ declare -p d declare -- d="a b hello c d"
同樣,就像別名一樣,在定義 shell 變數之前首先執行命令替換。
延遲執行
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