
いつもお世話になっております。
WindwsXPでDOSバッチを使ってテキストファイル中にある文字列1を文字列2に置換したいのです。
ネットをさまよっていて、こんな例を見つけました。
(参考にしたのはここです。http://www.fpcu.jp/dosvcmd/bbs/log/cat3/cat54/2- …)
======================
@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文を使う使わないにはこだわりません。
No.7ベストアンサー
- 回答日時:
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の行を取って実行するとよく分かります。
さっき気づいたのですが、pita-goraさんには前の質問でもお世話になっていたのでした。
http://okwave.jp/qa4253093.html
今回も丁寧な説明、ありがとうございます。たぶんどの本にも載っていないことなのでしょうね。
>このcall文の記述だと set l=%line:abc=xyz% という1行のバッチを呼び出しているのと同等の動作になります。
別バッチにしなくても別バッチのような動きをするのですね。
>◆単純に set l=%line:%mae%=%ato%% とした場合なぜうまくいかないか
むずかしいことをやさしく解説してくださって感激です。
>余談ですがバッチ実行時にどのように置き換えられるか見たい場合は、
>バッチ先頭のecho offの行を取って実行するとよく分かります。
やってみました。
echo offは何も考えずにつけていましたが、これからハマったときははずしてみます。
No.8
- 回答日時:
#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でもありえると思うのですが・・・。
No.5
- 回答日時:
懐かしいですね。
昔このサンプルを作りました。ご希望の件ですが
set l=%line:abc=xyz%
を
call set l=%%line:%mae%=%ato%%%
と書き換えれば希望の動作になると思います。
補足にもかいていますが、このバッチですが、変換するテキストに ">" "<" "|"などバッチのリダイレクションなどに使う記号がある場合や元のファイルに空行(改行のみの行)があるとうまく動かないのでそんな場合は素直にsedやawaやperlを使われた方がいいです。
何とあのサンプルを作られた方ですか。勝手に引用してしまってすみません。http://www.fpcu.jp/dosvcmd/bbs/log/cat3/cat54/2- …での質問者への丁寧な回答に、たいへん好感を持ちました(リダイレクトや空行の補足など)。技術的な知識だけでなく、人間としても素敵な方とお見受けします。
一方私はというと、ANo.3の方へのお礼にも書いたように、なぜcallを付けるのかが理解できていません。「ここを読め」の一言でいいので、何かヒントをいただけないでしょうか。
No.4
- 回答日時:
バッチファイルでもできるかも知れないけど、別のツールを使った方が現実的ではなかろうか。
そういう意味で#1さんに賛成。(sedやawkだと)
>それらをインストールするのに、他の部署の許可&作業依頼を出さないと
>いけないのです。できれば手持ちの道具ですませられればと。
参考にしたというページにも書いてあるけど"Windows Scripting Host"を使うのが現実的だと思いますがね。あくまでもバッチにこだわるのかな...
この回答への補足
回答ありがとうございます。私もWSHで書きたかったのですが、「DOSが一番信頼性がある」という職場なのです。これを機会に、sedやawkをインストールしてくれるよう働きかけてみます。
「ネットでもsedやawk、WHSを使えって言われましたよ」と言えば、少しは聞いてくれるかもです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
バッチでテキストファイルから...
-
コマンドプロンプトで2ヶ月前3...
-
バッチファイルで昨日の日付を取得
-
バッチファイル テキストファイ...
-
絶対パス名からファイル名を取...
-
呼び出し元バッチを知るには?
-
バッチファイルでDirで取得した...
-
大量のフォルダからひとつのフ...
-
コマンドプロンプトの「%1」と...
-
コマンドプロンプトのエラーに...
-
複数のbatファイルを自動実行し...
-
特定フォルダ内のファイルを自...
-
HTMLからのBATファイル実行
-
アクセス 壊れた? 「ファイ...
-
binファイルを解凍したいの...
-
.txtではなく.logの方が良いの...
-
エクセルの各セルの内容をそれ...
-
VBAでワークシートを引数として...
-
「読み取りと実行」と「読み取...
-
#include <Windows.h>というヘ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
バッチでテキストファイルから...
-
バッチファイルで昨日の日付を取得
-
バッチファイルでDirで取得した...
-
VBアプリケーションで終了コー...
-
コマンドプロンプトで2ヶ月前3...
-
コマンドプロンプト画面の閉じ...
-
絶対パス名からファイル名を取...
-
コマンドプロンプト(バッチファ...
-
コマンドプロンプト標準出力と...
-
バッチファイルで常に最新の現...
-
DOSのバッチで、変数中のファイ...
-
バッチファイル テキストファイ...
-
IPアドレスの第3オクテットだ...
-
コマンドプロンプトでファイル...
-
子バッチ内のキー入力処理へ自...
-
CMDの「Explorer」
-
バッチからバッチを逐次よぶ方法
-
バッチで自動的にディレクトリ...
-
コマンドプロンプト 半角スペー...
-
呼び出し元バッチを知るには?
おすすめ情報