亀の甲羅2

今日もまた朝とく起きて励まなん窓に明るきありあけの月

変数に格納された文字列”~”(チルダ)が展開されなかった件(eval を使おう)

$HOMEを表す”~”(チルダ)が変数に文字列として格納されているときに展開されない

こんな風に、ログのパスを決めておいて、そのパスにログ出力(リダイレクト)できるものかと思っていた。

$ log="~/.config/log/test.log"
$ echo "Start" >> $log

結果は以下の通り。

$ echo "Start" >> $log
bash: ~/.config/log/test.log: No such file or directory

なんで~?ってことで調べ始めた。
 
 

目次

本文

1. 基礎調査

◆パスをベタ書きして確認する

$ echo "Start" >> "~/.config/log/test.log"
bash: ~/.config/log/test.log: No such file or directory

→ パスを文字列として与えるとNG。  
 

$ echo "Start" >> ~/.config/log/test.log
(エラーなし→成功)

→ パスをパスとして与えるとOK
 
 
◆フルパスならどうか?

$ echo $HOME
/c/Users/user01

$ echo "Start" >> "/c/Users/user01/.config/log/test.log"
(エラーなし→成功)

→ なんか文字列として与えられた "~"(チルダ)が怪しい感じがする。

2. 調査結果

fohte.hateblo.jp

参考にさせていただいた。
"~"(チルダ)を含む文字列は、シェル実行時に$HOMEの値として展開されないらしい。

同じ実験をしてみた。

$ echo $HOME
/c/Users/user01

$ echo ~
/c/Users/user01 ・・・(A)

$ echo "~"
~ ・・・(B)

$ echo '~'
~ ・・・(C)

チルダが文字列として与えられた(B)(C)のパターンで、チルダチルダという文字として解釈されている。
一方で(A)では、いわゆるHOMEとして解釈され展開されている。

3. 文字列内のチルダを展開させたかったら「eval」コマンドを使おう

$ eval echo "~"
/c/Users/user01

→ "~"(チルダ)が展開されてechoされた。
 

$ eval 'echo "~"'
~

evalに与えるものを' 'シングルクォートでくくると結果が異なる。

4. 今回の課題の答えを探る

$ eval echo "Start1" ">>" "~/.config/log/test.log"
→ 成功。logに出力されていた。

ということで、evalに与えるコマンドの指定の仕方を3種類試してみた。  

$ eval echo "Start2" ">>" $log・・・(A)
→成功

$ eval "echo \"Start3\" >> $log"・・・(B)
→成功

$ eval 'echo \"Start3\" >> $log'・・・(C)
bash: ~/.config/log/test.log: No such file or directory

evalに与えるものは、””ダブルクォートでくくり内容展開される形で与えた方が良いみたい。(B)
''シングルクォートだと展開されない。 (C)
主要なところを文字列としてevalに与えればうまいこと解釈してくれるみたいだが、なんとなく気持ち悪い。(A)


追記:
itdoc.hitachi.co.jp

evalコマンドは、上記のページからすると、powershellの「Invoke-Expression」みたいなものらしい。


もう一つの解としては、$log変数自体に展開されたパスで格納して使いまわす手法がある。

$ logtmp="~/.config/log/test.log"

$ echo $logtmp
~/.config/log/test.log

$ log=`eval "echo $logtmp"` ・・・(A)

$ echo $log
/c/Users/hisabo/.config/log/test.log

 
log変数にチルダを展開して設定。echo使わなければならないのが、ちょっとダサい。
(ほかの方法があるかは後日にまわす)
   


バージョン情報

$ bash --version
GNU bash, version 4.4.23(1)-release (x86_64-pc-msys)
Copyright (C) 2016 Free Software Foundation, Inc.