- PR -

sedコマンドを使って選択的に置換する方法について

投稿者投稿内容
ぽんす
ぬし
会議室デビュー日: 2003/05/21
投稿数: 1023
投稿日時: 2005-02-16 20:38
引用:

juiceさんの書き込み (2005-02-16 14:24) より:
configureというのがよくわからなかったので調べてみたのですが、configureの書き方がわからないので時間がかかりそうです。。。


たいそうなconfigureスクリプトを書かなくても、自分のやりたい
ことだけやるスクリプトを書けばよいのであ?

引用:

ひとつお聞きしたいのですが、「configure(シェルスクリプト) → makefile作成 → make というように手順を分ける」と何かいいことがあるのでしょうか?


とりあえず、makeだけでは解決できない(解決方法があるかも
しれないけれど知らない)問題を解決するにはいいでしょうね。
juice
会議室デビュー日: 2005/02/14
投稿数: 9
投稿日時: 2005-02-17 12:52
ぽんすさん、アドバイスありがとうございます。

configureの作り方について少し調べていたのですが、やはり時間がかかりそうだったのと、作業量が増えそうだったのであきらめちゃいました。。

で、再びmakefileで実現できる方法を探していたところ、どうやら出来そうな感じになってきました。
以下が最新の状態です。
コード:
CHANGE_HEADER = BBB.h DDD.h EEE.h FFF.h … #変更対象になるヘッダを定義。
CCC_AAA.c : AAA.c
	cp $< $@
	@( for d in $(CHANGE_HEADER) _ ; do \
	    if [ "$$d" != "_" ] ; then \
		cp $@ $@_ ; \
		sed -e "s/^\#include \"$$d\"/\#include \"CCC_$$d\"/" \
		-e "s/^\#include <$$d>/\#include <CCC_$$d>/" $@_ > $@; \
	    fi ; \
	done ) ;
	rm $@_


この状態でCCC_AAA.cだけは望んだ結果が得られました。ただ、"sed","cp","rm"などのコマンドをソースファイル1つあたり50回ほど呼び出すことになるのでmakeが遅くなりそうですが…。まだ多少修正が必要な部分などがあるので、これらがクリアでき次第、またこちらにフィードバックさせていただきます。
ありがとうございました。
ぽんす
ぬし
会議室デビュー日: 2003/05/21
投稿数: 1023
投稿日時: 2005-02-17 13:10
ん〜、シェルスクリプトというものを全くご存知ないのでしょうか?

Cのソースを書くとか、Makefileを書くとかよりも、ずっと
容易に習得できるものですが...
シェルスクリプトを使うのと使わないのとでは作業効率がまるで
違ってくる場面がしばしば存在するので、覚えておいたほうが
よいかと思うです。
# べつにシェルスクリプトの達人にならなくてもよくて、
# 1時間くらい『UNIXプログラミング環境』か何か読めば
# いいんじゃないかなあ...
juice
会議室デビュー日: 2005/02/14
投稿数: 9
投稿日時: 2005-02-17 14:55
お疲れ様です。
引用:
ぽんすさんの書き込み (2005-02-17 13:10) より:
ん〜、シェルスクリプトというものを全くご存知ないのでしょうか?


…よくわかっていません。。
ぽんすさんのご提案がよくわからないのですが、configureというのはつくらずにシェルスクリプトを書いてそれをmakefileから実行させればよい、というお考えなのでしょうか?

configureを作るのをあきらめたのは、この中でデバッグオプションやパスやその他いろいろの設定を記述しなければいけないのでは?と考えたからです。現在の手書きのmakefileとおなじ設定を再現できるかどうかわからないため、遠回りになるという印象を持ちました。

ぽんすさんのご提案はconfigureを作る/makefileを作成させるということとは別の話なのでしょうか?
ぽんす
ぬし
会議室デビュー日: 2003/05/21
投稿数: 1023
投稿日時: 2005-02-17 20:56
configureはふつう、シェルスクリプトですが...
でもそんなことはどうでもよくて。

私が言っているのは、Utaさんが書かれている
> configure(シェルスクリプト) → makefile作成 → make
ということです。
Uta
常連さん
会議室デビュー日: 2004/05/17
投稿数: 37
投稿日時: 2005-02-18 09:49
ぽんすさんが既に仰っていますが、configureというのは通例上そのように呼ばれている
(ファイル名も[configure]となっている)だけで、中身はシェルスクリプトです。
まぁOpenSSL等のようにPerlスクリプトを利用するものもありますが。

configureの役割は、アプリケーションをインストールする環境
(OSの種類やバージョン・前提のソフトウェアの有無やパス 等々)を調べて、
それに合わせて Makefile を作成することです。

オープンソースのアプリケーションでは、様々な人が様々な環境で利用できるように
configureスクリプトで複雑な処理をしていますが、
juiceさんのアプリケーションをインストールする環境は限定されていると予想できますので、
簡単なスクリプトを書いておけばいいのではないでしょうか。

具体的には、下記の2点でよいのかと。
1.ソースファイル・ヘッダファイルをリネームして[change]ディレクトリにコピー
2.[change]ディレクトリのソースファイル内の #include 部分を編集する
  ↑ その際条件分岐等で書き換えるものと書き換えないものを区別する


なお、私は構築・運用・保守側の経験しかありませんので
この方法が開発の作法的によいものなのか全く保証できません。
ソースの編集をしてる時点でconfigureスクリプトの担当範囲を
超えているような気もしますし。

当スレッドの初期にMMXさんが
引用:
ソースの変更なら #ifdef などがノーマルと思いますが
=================================================
あるいは、インクルード順位の最高位のディレクトリに 、BBB → #INCLUDE CCC_BBB をする間接インクルードの中継地でも置くとか。ですね


と仰っている点に関しても、私には何のことだか解りかねますが
調査してみるとよいのではないでしょうか。
juice
会議室デビュー日: 2005/02/14
投稿数: 9
投稿日時: 2005-02-22 15:44
ぽんすさん、Utaさん、アドバイスありがとうございます。
お返事に間が空いてしまい申し訳ありません。
どうも私が組み込みSWの開発をしているためかそれともただ単に私の知識不足なのか(これが最も大きいようには思いますが)お二方のアドバイスが十分に理解できません。。。すみません。。

引用:

Utaさんの書き込み (2005-02-18 09:49) より:
configureの役割は、…(中略)… Makefile を作成することです。


ということは、
 configureを作る(書く)→configureがmakefileを作る→makefileがコンパイルを行う
ということですよね?

 つまり、コマンドラインで"make"と入力したときに実行されるのは一番最後の「makefileがコンパイルを行う」という段階のみである、という理解でよろしいでしょうか?
 また、この方法を採用し、"やりたいことをconfigureでやった"場合、"configureがmakefileを作る"時に、一緒にソースも改変し、目的のソースが出来上がってからmakefileをもとにコンパイルが行われ、makefileが出来てからはソースの改変は行われないと理解しています。コンパイルのたびにコピー→リネーム→編集が自動的に行われるようにはならないのでは、と考えたのですが間違っているでしょうか?

MMXさんのご提案に関しては以下のように解釈していました。
コード:
「ソースの変更なら #ifdef などがノーマルと思いますが」
 →以下のようにソースの中でもともと区切ってしまう。
  これが一番簡単ですが、ソースの数が多く正しく反映させるのに手間がかかる
  ことと、無駄な改変が入るため避けました。
   #ifdef CHANGE
    #include "CCC_AAA.h"
   #ifndef CHANGE
    #include "AAA.h"
   #endif

「あるいは、インクルード順位の最高位のディレクトリに 、
 BBB → #INCLUDE CCC_BBB をする間接インクルードの中継地でも置くとか。ですね」
 →新たなヘッダを用意してそこに
  #define CCC_AAA.h AAA.h などとして変換する。
  これも考えましたが、新たなヘッダをすべてのソースでincludeしなければならな
  くなるため断念しました。



また、makefileのほうは、前回ご報告させていただいた時点でほぼ望みどおりの動きをするものが出来ており、現在は以下のような状態になっています。
コード:
define change-file
	cp $< $@		#AAA.cをCCC_AAA.cにコピー
	@( for d in $(CHANGE_HEADER) _ ; do \	#ヘッダ名を変えながらループ
	    if [ "$$d" != "_" ] ; then \		#ループは文字"_"が出てくるまで
	        cp $@ $@_ ; \			#CCC_AAA.cをCCC_AAA.c_にコピー
	        sed -e "s/^\#include \"$$d\"/\#include \"CCC_$$d\"/" \
	        -e "s/^\#include <$$d>/\#include <CCC_$$d>/" $@_ > $@; \
			#「include"BBB.h"」を「include"CCC_BBB.h"」に置換し、
			#「include<BBB.h>」を「include<CCC_BBB.h>」に置換する。
			#このときの元ファイルはCCC_AAA.c_で結果はCCC_AAA.cに出力
	    fi ; \
	done )
	@rm $@_		#CCC_AAA.c_をリムーブ
endef

CCC_AAA.c : AAA.c
	$(change-file)		#上記コマンド列を実行
CCC_BBB.h : BBB.h
	$(change-file)

参考URL:http://meraman.dip.jp/make/gmake.html


私自身の知識不足のため具体的な方法までたどり着けなかったこと、またその他の事情によりたくさんのアドバイスをいただいたにもかかわらず、それらを反映させることが出来ず申し訳ありません。頑固なやつだとお思いの方もいらっしゃるかと存じますがご理解くださいませ。
シェルスクリプトについてはこの件とは別にでも勉強したいと考えております。いろいろと教えて頂き、ありがとうございました。
juice
会議室デビュー日: 2005/02/14
投稿数: 9
投稿日時: 2005-02-22 15:44
ぽんすさん、Utaさん、アドバイスありがとうございます。
お返事に間が空いてしまい申し訳ありません。
どうも私が組み込みSWの開発をしているためかそれともただ単に私の知識不足なのか(これが最も大きいようには思いますが)お二方のアドバイスが十分に理解できません。。。すみません。。

引用:

Utaさんの書き込み (2005-02-18 09:49) より:
configureの役割は、…(中略)… Makefile を作成することです。


ということは、
 configureを作る(書く)→configureがmakefileを作る→makefileがコンパイルを行う
ということですよね?

 つまり、コマンドラインで"make"と入力したときに実行されるのは一番最後の「makefileがコンパイルを行う」という段階のみである、という理解でよろしいでしょうか?
 また、この方法を採用し、"やりたいことをconfigureでやった"場合、"configureがmakefileを作る"時に、一緒にソースも改変し、目的のソースが出来上がってからmakefileをもとにコンパイルが行われ、makefileが出来てからはソースの改変は行われないと理解しています。コンパイルのたびにコピー→リネーム→編集が自動的に行われるようにはならないのでは、と考えたのですが間違っているでしょうか?

MMXさんのご提案に関しては以下のように解釈していました。
コード:
「ソースの変更なら #ifdef などがノーマルと思いますが」
 →以下のようにソースの中でもともと区切ってしまう。
  これが一番簡単ですが、ソースの数が多く正しく反映させるのに手間がかかる
  ことと、無駄な改変が入るため避けました。
   #ifdef CHANGE
    #include "CCC_AAA.h"
   #ifndef CHANGE
    #include "AAA.h"
   #endif

「あるいは、インクルード順位の最高位のディレクトリに 、
 BBB → #INCLUDE CCC_BBB をする間接インクルードの中継地でも置くとか。ですね」
 →新たなヘッダを用意してそこに
  #define CCC_AAA.h AAA.h などとして変換する。
  これも考えましたが、新たなヘッダをすべてのソースでincludeしなければならな
  くなるため断念しました。



また、makefileのほうは、前回ご報告させていただいた時点でほぼ望みどおりの動きをするものが出来ており、現在は以下のような状態になっています。
コード:
define change-file
	cp $< $@		#AAA.cをCCC_AAA.cにコピー
	@( for d in $(CHANGE_HEADER) _ ; do \	#ヘッダ名を変えながらループ
	    if [ "$$d" != "_" ] ; then \		#ループは文字"_"が出てくるまで
	        cp $@ $@_ ; \			#CCC_AAA.cをCCC_AAA.c_にコピー
	        sed -e "s/^\#include \"$$d\"/\#include \"CCC_$$d\"/" \
	        -e "s/^\#include <$$d>/\#include <CCC_$$d>/" $@_ > $@; \
			#「include"BBB.h"」を「include"CCC_BBB.h"」に置換し、
			#「include<BBB.h>」を「include<CCC_BBB.h>」に置換する。
			#このときの元ファイルはCCC_AAA.c_で結果はCCC_AAA.cに出力
	    fi ; \
	done )
	@rm $@_		#CCC_AAA.c_をリムーブ
endef

CCC_AAA.c : AAA.c
	$(change-file)		#上記コマンド列を実行
CCC_BBB.h : BBB.h
	$(change-file)

参考URL:http://meraman.dip.jp/make/gmake.html


私自身の知識不足のため具体的な方法までたどり着けなかったこと、またその他の事情によりたくさんのアドバイスをいただいたにもかかわらず、それらを反映させることが出来ず申し訳ありません。頑固なやつだとお思いの方もいらっしゃるかと存じますがご理解くださいませ。
シェルスクリプトについてはこの件とは別にでも勉強したいと考えております。いろいろと教えて頂き、ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)