dポイントプレゼントキャンペーン実施中!

お世話になります。

一度変数に文字列として格納したsedコマンドの実行についての質問です。
以下、「実装1」のように、「あるファイルの最終行を除外して別のファイルに書き込む」という処理を行おうとしています。
ログ出力などの関係で、実行するコマンドを一度変数に格納する必要があるのですが
一度変数に格納して実行すると「実装2」のようにエラーが出てしまいます。
変数に格納したsedコマンドを実行するにはどのようにすればいいでしょうか?

なお、シェルはbashです。
実行例ではターミナルから直接実行していますが、実際にはシェルスクリプトにして実行します。

以上、どなたかご教示頂けないでしょうか。

■実装1
[root@localhost tmp]# cat /tmp/data
aaa
bbb
ccc
[root@localhost tmp]# sed -e '$d' /tmp/data >/tmp/data2
[root@localhost tmp]# cat /tmp/data2
aaa
bbb
[root@localhost tmp]#

■実装2
[root@localhost tmp]# CMD='sed -e $d /tmp/data >/tmp/data2'
[root@localhost tmp]# echo $CMD
sed -e $d /tmp/data >/tmp/data2
[root@localhost tmp]# $CMD
aaa
bbb
sed: >/tmp/data2を読み込めません: そのようなファイルやディレクトリはありません
[root@localhost tmp]#

A 回答 (2件)

No1です。


その理解で合ってます。

それら3処理以外にも * 等のファイルマッチの展開や、" ' \ によるクォート外しとかありますが。
    • good
    • 0
この回答へのお礼

>それら3処理以外にも * 等のファイルマッチの展開や、" ' \ によるクォート外しとかありますが。
なるほど、他の処理については機会があったら調べてみます。

本件解決しましたのでBAとさせて頂きます。
迅速な回答大変有難うございました。

お礼日時:2014/02/13 23:36

$CMDの変数展開の前にリダイレクトの解釈がされるので、>/tmp/data2 がファイルへのリダイレクト指定で無く、>まで含めたファイル名として扱われます。



変数内のリダイレクトを処理するためには、evalが必要。evalするので$にはクォートが必要。
$ CMD='sed -e \$d /tmp/data >/tmp/data2'
$ echo $CMD
sed -e \$d /tmp/data >/tmp/data2
$ eval $CMD
    • good
    • 0
この回答へのお礼

早々の回答ありがとうございます。

回答頂きました通り、evalコマンドをかませることで動作することを確認致しました。

>$CMDの変数展開の前にリダイレクトの解釈がされるので、>/tmp/data2 がファイルへのリダイレクト指定で無く、>まで含めたファイル名として扱われます。
細かな話で申し訳無いのですが、この部分が理解できていません。
次のような解釈で合っていますでしょうか?(散らかった文章ですいません)

(1)通常シェルは次の順にコマンドを処理する。
・リダイレクトの解釈
・変数の展開
・コマンドの実行

(2)今回の実装2では「リダイレクトの解釈」の時点で$CMDが展開されていなかったため
  $CMDのリダイレクト部分は、sedの変数の1つとして扱われた。

(3)evalコマンドを使用することで、上記3処理が2回走り、次のような処理になったためうまく動いた。
・リダイレクトの解釈 … eval $CMDのためリダイレクトなし
・変数の展開 … eval sed -e \$d /tmp/data >/tmp/data2
・コマンドの実行 … ※evalの引数でもう一周
・リダイレクトの解釈 … sed -e $d /tmp/data >/tmp/data2 のためdata2に書き込み
・変数の展開 … 変数なし
・コマンドの実行 … sed -e $d /tmp/data >/tmp/data2

以上、よろしくお願いします。

お礼日時:2014/02/13 22:24

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!