問題ID:22156について

  • フォーラムは新サイトへ移行しました。
  • このフォーラムではゲスト投稿が禁止されています
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 .2 .3 .4 | 投稿日時 2019-6-18 13:37
kan1111  新米   投稿数: 5
いつも利用させていただき、ありがとうございます。
何度解説を読んでも理解できない点があるので、どなたかご教授ください。

<問題文>
変数DATEに「date」という文字列(現在の日時を表示するコマンド)を格納した。
以下のコマンドの実行結果は次のうちどれか。

$ echo "$DATE"

<選択肢>
 ・現在の日時
 ・$date
 ・DATE
 ・date ←正解
 ・$DATE

解説内容の【echoコマンドの引数にある「$DATE」は「"」で囲まれていますが、「$」は無視されない為、文字列ではなく変数として扱われます。】までは理解できています。
$が文字列でなく、「変数DATE」と認識されていたら、「変数DATE」に格納されている「現在の日時を表すコマンド」が認識され、「現在の日時」が表示されないのでしょうか?

他の変数DATEの設問(22155、22157、22158)の解説も比べてみてもどうして22156だけは「現在の日時」がでずに「date」という文字列のまま表示されるのですか?メタキャラクタの違いについては認識が違っていないと思うのですが…

恐れ入りますが、よろしくお願いいたします。
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2019-6-18 14:47 | 最終変更
arashi1977  長老 居住地: 広島  投稿数: 1715
引用:
$が文字列でなく、「変数DATE」と認識されていたら
誤解がないように念のため。「$が変数DATEと認識」ではなく「$DATEが変数DATEと認識」です。


引用:
「変数DATE」に格納されている「現在の日時を表すコマンド」が認識され、「現在の日時」が表示されないのでしょうか?
うーんと、「変数DATEに格納されているのは"date"という文字列」であって「現在の日時を表すコマンドそのもの」や「コマンドの実行結果」ではないです。
この"date"をシェルがどう扱うかで動きが変わるんですね。

ご質問の問題では
・「echo "$DATE"」となっているので、シェルは「echo date」と解釈する。この場合実際に実行すると単にechoコマンドに「date」という文字列を渡すので、結果として「date」と出力することになります。
※シェルの動作をわかりやすくするために「set -x」やっときます。
$ set -x

# シェル変数DATEにdateという文字列を格納
$ DATE=date
+ DATE=date

# 設問のコマンド。dateとだけ理解しているので「echo date」と同じこと
$ echo "$DATE"
+ echo date
date

# 普通に「echo date」をやるとこう
$ echo date
+ echo date
date

・kan1111さんの気にする【「現在の日時を表すコマンド」が認識され】るためにはバッククオートなりを使って「コマンドとして解釈」させる必要があります。
$ echo `$DATE`
++ date ←「`$DATE`」を解釈してコマンドとして実行している
+ echo 2019年 $'6�\234\21018�\227�' $'�\201��\233\234�\227�' $'14�\231\20244�\210\20651�\222' JST
2019年 6月18日 火曜日 14時44分51秒 JST

$ echo $($DATE)
++ date ←上と同じこと
+ echo 2019年 $'6�\234\21018�\227�' $'�\201��\233\234�\227�' $'14�\231\20245�\210\20605�\222' JST
2019年 6月18日 火曜日 14時45分05秒 JST
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2019-6-18 15:36
kan1111  新米   投稿数: 5
解説ありがとうございます。

実際私も投稿前にLinuxを触って問題文通りにやってみましたが、確かに文字列になった記憶はあります。
しかし、他類似設問(22155〜22158)は解説通りにならず、私の操作が違うのかと思ったので解説を再度熟読し、22156のみ理解しきれず質問させていただいた次第です。
実際こうなるから、ではなく頭で理屈を理解できないと気になったままなので、お手数ですがもう少し教えていただけると助かります。

変数DATEに格納されているのは"date"という文字列
という点は理解していますが、
問題文通りdate=現在の日時を表示するコマンドという前提の下であれば、dateが表示される=現在の日時が引き出される、ではないのでしょうか?

例えば、問題ID:22157の回答は【現在の日時】となっており、【$DATE=date=現在の日時】という風になっているかと思います。メタキャラクタが違うことは承知していますが、前提条件【$DATE=date=現在の日時】が同じなのであれば【date=現在の日時】にはならないのでしょうか?

それか、そもそも問題文の【現在の日時を表示するコマンドを格納】という部分は気にしすぎなくてもよくて、【"】で囲まれた【$変数】は、「変数に格納されたものがコマンドでも、コマンドの結果ではなくコマンド自体が文字数として表示される」という理解をすれば良い、ということなんでしょうか?

私が何故ここに引っかかっているのか、うまく説明ができなくて申し訳ありません。
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2019-6-18 22:43
arashi1977  長老 居住地: 広島  投稿数: 1715
ちょっと深読みというか、補完し過ぎな感じがします。順を追って。

引用:
変数DATEに格納されているのは"date"という文字列
という点は理解していますが、
ここはOKですね。

引用:
問題文通りdate=現在の日時を表示するコマンドという前提の下であれば、dateが表示される=現在の日時が引き出される、ではないのでしょうか?
ここ!
「date=現在の日時を表示するコマンド」をどう理解するか、というところでずれている気がします。

例えば。
「変数CALにcalという文字列を格納した」だけあって、「echo `$CAL`の実行結果は?」って聞かれたときにどういう結果が出るかぱっとわかりますか?

ご存知ならいいのですが、「cal」ってカレンダーを表示してくれるコマンドなんです。
$ cal
      6月 2019
日 月 火 水 木 金 土
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
でもそれを知らない人がこの問題見ても「バッククオートだからcalというコマンドが実行されるはず」「でもcalってコマンドは何するコマンド?」「そもそもcalってコマンドあるの?」って疑問に思うかもしれません。そういった事にならないように補足として「(カレンダーを表示するコマンド)」とあったら問題ないですよね?

【「date」という文字列(現在の日時を表示するコマンド)】という記述は、上述したのと同じように「dateってコマンドあるの?」とか言う疑問を持たせないための補足なんじゃないかと思います。
※引掛けってほどでもないですが、「現在の日時を表示するコマンド名と同じ文字列」と理解すればそんな大きくずれてないかな?

引用:
例えば、問題ID:22157の回答は【現在の日時】となっており、【$DATE=date=現在の日時】という風になっているかと思います。メタキャラクタが違うことは承知していますが、前提条件【$DATE=date=現在の日時】が同じなのであれば【date=現在の日時】にはならないのでしょうか?
問題ID:22157はバッククオートに関する問題ですので、前の私の投稿にもある通り「受け取ったものをコマンドとして実行」するのが正しいです。なので「【$DATE=date=現在の日時】」ではなく「`$DATE`=【シェル上でのdateコマンド実行結果】=現在の日時」となっているだけで、「$DATE=【シェル上でのdateコマンド実行結果】」ではありません。
この時点で「前提条件」と想定されている部分は根本的に間違っている、ということになります。

dateでやるから混乱するのかもしれませんね。例えば以下のように存在しないコマンドを使ったらピンとくるかもしれません。
$ myname
-bash: myname: command not found ←mynameなんてコマンドはない
$ DATE=myname ←変数DATEにmynameを格納した
$ set | grep DATE
DATE=myname ←変数DATEにはmynameという文字列が格納されている
$ echo "$DATE"
myname ←問題ID:22156のとおり、格納されている文字列が出力されている
$ echo `$DATE` ←バッククオートで囲った場合
-bash: myname: command not found ←mynameというコマンドを実行しようとしてエラーになっている
←この空行はechoコマンドの実行結果(何も表示されなかった)
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2019-6-19 9:03
kan1111  新米   投稿数: 5
丁寧な解説、ありがとうございます。

最後の例で何となく理解しました。
「`」で囲まれた文字列は変数に格納されたコマンドも展開するが、「"」で囲まれた文字列は変数の展開のみを行い、変数に格納されたコマンドは展開しない
という解釈で間違いないでしょうか?
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2019-6-19 9:48
arashi1977  長老 居住地: 広島  投稿数: 1715
引用:
「`」で囲まれた文字列は変数に格納されたコマンドも展開するが、「"」で囲まれた文字列は変数の展開のみを行い、変数に格納されたコマンドは展開しない
もーちょっと厳密に言うと、バッククオート(`)で囲まれた範囲は「変数かどうかによらず、コマンドとして実行する」ものです。例えば以下のようなことです。
$ echo `cat /etc/redhat-release`
CentOS Linux release 7.6.1810 (Core)

それの何が嬉しいの?ってこともあると思いますが、例えば
# ls -l
合計 0 ←今このディレクトリにはなにもない
# ls -1 | wc -l
0 ←lsコマンドで出力される行数は0
# touch testfile-`ls -1 | wc -l`  ←上記のコマンドの結果を利用して
# ls -l
合計 0
-rw-r--r--. 1 root root 0  6月 19 09:43 testfile-0 ←テストファイルに通番(0)を付与して作成
# ls -1 | wc -l
1 ←1ファイルあるので、lsコマンドの出力行数は1
# touch testfile-`ls -1 | wc -l` ←連続して同じコマンドを実行
# ls -l
合計 0
-rw-r--r--. 1 root root 0  6月 19 09:43 testfile-0
-rw-r--r--. 1 root root 0  6月 19 09:43 testfile-1 ←ファイルの通番がファイル数に応じて増加している
みたいな感じで、「コマンドの実行結果を文字列としてシェルに渡す」事ができるので、コマンドライン作業に柔軟性が出てくるんです。
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2019-6-19 10:30
kan1111  新米   投稿数: 5
ありがとうございます!

2つ前の「myname」の例も併せて考えると、「`」は囲んだ文字列を、コマンドの有無に関わらずコマンドとして実行しているんですね。

「`」「"」の違いについて、問題の解説に記載されているメタキャラクタの表の「囲まれた文字列(変数の場合は格納されている値)をコマンドとみなす」をいまいち把握できておらず、どちらも「囲まれた文字列が変数の場合は展開できる」というように浅く考えていたため起こった勘違いのようでした。
改めて解説を読むと、考えすぎて「'」「"」「`」を混同させてしまっていたことに気づきました。

丁寧に教えていただいて本当にありがとうございました。

  >フォーラム検索へ


Copyright (c) 2020 Ping-t All rights reserved.