bash - type -aが「$(printf 'a')」を実行するのはなぜですか?元のエイリアスを元に戻すことはできますか? [コピー]

bash - type -aが「$(printf 'a')」を実行するのはなぜですか?元のエイリアスを元に戻すことはできますか? [コピー]

私がこれを聞いた後質問2日前、私は〜/.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

次の2つのコマンドを試して結果を確認してください。

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

デフォルトでは、一重引用符は「元の生の文字列」を提供しますが、二重引用符内のすべての内容は、エイリアスに割り当てられる前に評価されます。

ただし、2番目のコマンドの出力には、「a」の周りの一重引用符がありません。引用符の損失を防ぐために、引用符を再確認して追跡する必要があります。\"一重引用符の中には使用できないことを除いて、内側の二重引用符を使用する必要があるのと同じです。あなたはそのようなものを使うべきです'\''

したがって、エイリアスの代わりに関数を使用して、引用符で保護されていることを心配する必要がないことをお勧めします。また、コマンドラインでファイル名を指定することができ、エイリアスはファイルに何かをパイプする場合にのみ機能します。

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

関連情報