- ベストアンサー
DOSのバッチで、テキストファイル中の文字を置換したい
いつもお世話になっております。 WindwsXPでDOSバッチを使ってテキストファイル中にある文字列1を文字列2に置換したいのです。 ネットをさまよっていて、こんな例を見つけました。 (参考にしたのはここです。http://www.fpcu.jp/dosvcmd/bbs/log/cat3/cat54/2-0391.html) ====================== @echo off if "%1"=="" goto end set fname=%1 copy %fname% org >nul type nul >%fname% for /f "tokens=1* delims=" %%a in ( org ) do (set line=%%a&& call :sub) del org goto end :sub :この1行下の acb=xyz に置換前と置換後の文字列を指定する。 set l=%line:abc=xyz% echo %l%>>%fname% goto :EOF :end ====================== これをsample.batという名前で保存し、DOSのウィンドウでsample < a.txt と打つと、a.txtファイル中の"abc"が"xyz"に置き換わります。 これに手を入れて置換前と置換後の文字列を可変にしたく思い、sub中に set mae=abc set ato=xyz の2行を加え、変数に値を設定するようにしました。 ところが、次の1行の書き変え方がわかりません。 set l=%line:abc=xyz% を set l=%line:%abc%=%xyz%% のように変えてみましたが、うまく動きません。 どなたかご教授いただけませんか。DOSだけでファイル中の文字列の置換ができればset文を使う使わないにはこだわりません。
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
No.5 です。 >勝手に引用してしまってすみません。 皆さんに参考にしてもらうために回答しているので気になさらずに引用してください。 さてご質問の件ですが、 ◆予備知識 まず、環境変数を%で囲むと、バッチがその行を実行するときに環境変数の中身に置き換えられることを理解してください。 例) set mae=abc set ato=xyz echo %mae% %ato% ←※ ※の行が実行されるとき、実際は echo abc xyz と置き換えられてecho文が実行されます。 また、バッチ内では %% と%が2つ並んだ記述は1つの%に置き換えられます。 例)echo 10割は100%% 10割は100% ◆今回の場合 call set l=%%line:%mae%=%ato%%% ↓実行されるときに以下のように置き換えられます。 call set l=%line:abc=xyz% 置き換え後に call 文が実行されます。このcall文の記述だと set l=%line:abc=xyz% という1行のバッチを呼び出しているのと同等の動作になります。従って環境変数lineに入っている文字列のabcがxyzに置き換えられた結果が環境変数lに代入されます。 call文でワンクッション置いて、先に環境変数の mae と ato (と%%)だけ評価(環境変数の中身に置き換え)するようにしています。 ◆単純に set l=%line:%mae%=%ato%% とした場合なぜうまくいかないか set文の右辺の各要素を分けて書くと %line:%(line: という環境変数の中身)→そんな変数は定義していないので空に置き換え mae %=%(= という環境変数の中身)→そんな変数は定義できないので空に置き換え ato %% → % に置き換え と解釈されて 環境変数lには maeato% という文字列が代入されてしまいます。 余談ですがバッチ実行時にどのように置き換えられるか見たい場合は、 バッチ先頭のecho offの行を取って実行するとよく分かります。
その他の回答 (7)
- notnot
- ベストアンサー率47% (4900/10358)
#3です。 何故そうなるかというと、「やってみるとそうなるから」としか言えないです。具体的には#7の方がお書きのような%についての処理が二回起こります。call を重ねれば三回、四回も可能です。 「1行のバッチと同じ」かというと、厳密には違う部分もあるので、別の応用をするなら「%の処理が二回起こる」と考えた方が良いでしょう。#7の方も「このcall文の記述だと」と書いてます。 念のためですが、ヘルプには書いてないので、Undocumentedな仕様ということになります。 Documentedな使用の範囲でやるなら、本当に1行のバッチファイルを作ります。 echo set l=%%line:%mae%=%ato%%% > sub000.bat cal sub000.bat del sub000.bat >「ネットでもsedやawk、WHSを使えって言われましたよ」と言えば、少しは聞いてくれるかもです。 Windows Script Hostは標準装備ですよ。正規表現も使えるし。
お礼
notnotさん、いろいろありがとうございます。 >call を重ねれば三回、四回も可能です。 >1行のバッチと同じ」かというと、厳密には違う部分もあるので 大変勉強になります。 >ヘルプには書いてないので、Undocumentedな仕様ということになります。 やはりそうですか。地道に努力していくほかなさそうですね。今回、本当に勉強になりました。 >Windows Script Hostは標準装備ですよ。正規表現も使えるし。 上司が「WSHはOSのバージョンによって動作が異なる。DOSが一番信頼性がある」というスタンスなのです。バージョンによって動作が異なるのはDOSでもありえると思うのですが・・・。
- redfox63
- ベストアンサー率71% (1325/1856)
/v オプションは CMD.EXEのオプションなので バッチの起動をする際に cmd.exe /v:on /C バッチファイル名 といった具合にします
お礼
ありがとうございます。教えてちゃんですみません。
- pita-gora
- ベストアンサー率70% (102/145)
懐かしいですね。昔このサンプルを作りました。 ご希望の件ですが set l=%line:abc=xyz% を call set l=%%line:%mae%=%ato%%% と書き換えれば希望の動作になると思います。 補足にもかいていますが、このバッチですが、変換するテキストに ">" "<" "|"などバッチのリダイレクションなどに使う記号がある場合や元のファイルに空行(改行のみの行)があるとうまく動かないのでそんな場合は素直にsedやawaやperlを使われた方がいいです。
お礼
何とあのサンプルを作られた方ですか。勝手に引用してしまってすみません。http://www.fpcu.jp/dosvcmd/bbs/log/cat3/cat54/2-0391.htmlでの質問者への丁寧な回答に、たいへん好感を持ちました(リダイレクトや空行の補足など)。技術的な知識だけでなく、人間としても素敵な方とお見受けします。 一方私はというと、ANo.3の方へのお礼にも書いたように、なぜcallを付けるのかが理解できていません。「ここを読め」の一言でいいので、何かヒントをいただけないでしょうか。
バッチファイルでもできるかも知れないけど、別のツールを使った方が現実的ではなかろうか。そういう意味で#1さんに賛成。 (sedやawkだと) >それらをインストールするのに、他の部署の許可&作業依頼を出さないと >いけないのです。できれば手持ちの道具ですませられればと。 参考にしたというページにも書いてあるけど"Windows Scripting Host"を使うのが現実的だと思いますがね。あくまでもバッチにこだわるのかな...
補足
回答ありがとうございます。私もWSHで書きたかったのですが、「DOSが一番信頼性がある」という職場なのです。これを機会に、sedやawkをインストールしてくれるよう働きかけてみます。 「ネットでもsedやawk、WHSを使えって言われましたよ」と言えば、少しは聞いてくれるかもです。
- notnot
- ベストアンサー率47% (4900/10358)
set mae=abc set ato=xyz call set l=%%line:%mae%=%ato%%%
お礼
魔法のようにできました。でも、なぜできたのかがわかりません。 callというからにはサブルーチン?サブルーチンは書いてないのに? お願いです。あと一言ヒントをください。
- redfox63
- ベストアンサー率71% (1325/1856)
バッチの中で環境変数を書き換える場合 起動するCMD.EXEに対して /v:on のオプションを与えましょう これを与えないとバッチファイルforコマンドなどでの環境変数の変更が有効になりません
お礼
すみません、超初心者なものでおっしゃることがよくわかりません。 オプションを与えるというのは、バッチファイルの中に書くものでしょうか。
- Tacosan
- ベストアンサー率23% (3656/15482)
ふつうは sed とか awk とか perl とかを使うような気がする. わざわざいばらの道を切り開かんでも....
お礼
それらをインストールするのに、他の部署の許可&作業依頼を出さないといけないのです。できれば手持ちの道具ですませられればと。
お礼
さっき気づいたのですが、pita-goraさんには前の質問でもお世話になっていたのでした。 http://okwave.jp/qa4253093.html 今回も丁寧な説明、ありがとうございます。たぶんどの本にも載っていないことなのでしょうね。 >このcall文の記述だと set l=%line:abc=xyz% という1行のバッチを呼び出しているのと同等の動作になります。 別バッチにしなくても別バッチのような動きをするのですね。 >◆単純に set l=%line:%mae%=%ato%% とした場合なぜうまくいかないか むずかしいことをやさしく解説してくださって感激です。 >余談ですがバッチ実行時にどのように置き換えられるか見たい場合は、 >バッチ先頭のecho offの行を取って実行するとよく分かります。 やってみました。 echo offは何も考えずにつけていましたが、これからハマったときははずしてみます。