- ベストアンサー
【DOSバッチ開発】末尾のタブのみ削除したい
DOSバッチ開発で困っています。 あるテキストファイル(DBから出力したタブ区切りのファイル)に n行データが入っています。 1行につき133項目もっています。 各行の最後の項目は必ずタブがあります。 この末尾のタブのみ削除してファイルを置き換えたいです。 バッチ開発経験が浅いため、うまく作成ができません。 よろしくお願いいたします。
- みんなの回答 (10)
- 専門家の回答
質問者が選んだベストアンサー
UTF-8ですか。。。。#2に書いたようなバッチで直接扱うのは不可能です。扱えるのはシフトJISだけ。最初からUTF-8とわかっていれば。 VBScriptだとやや面倒ですが、扱えます。 @echo off rem 入出力ファイル名の設定 set FILEIN=%~1 set FILEOUT=%~1.tmp rem VBSファイルを作成する echo > tmp.vbs set fileIN = createobject("adodb.stream") echo >>tmp.vbs set fileOUT = createobject("adodb.stream") echo >>tmp.vbs fileIN.open echo >>tmp.vbs fileIN.charset = "UTF-8" echo >>tmp.vbs fileIN.loadfromfile "%FILEIN%" echo >>tmp.vbs str = fileIN.readtext echo >>tmp.vbs fileOUT.open echo >>tmp.vbs fileOUT.charset = "UTF-8" echo >>tmp.vbs fileOUT.writetext Replace(str, vbTab^&vbCRLF, vbCRLF) echo >>tmp.vbs fileOUT.savetofile "%FILEOUT%", 2 echo >>tmp.vbs fileOUT.close echo >>tmp.vbs fileIN.close rem メイン処理 cscript //nologo tmp.vbs rem エラーなら終了 if errorlevel 1 exit /b 1 rem 後始末 del "%FILEIN%" tmp.vbs move "%FILEOUT%" "%FILEIN%" VBSプログラム内のでエラー処理は手抜きです。
その他の回答 (9)
- notnot
- ベストアンサー率47% (4900/10359)
>No.7の補足に書いた以下ソースをutf-8対応で改修して頂けませんか。 ? それが、No9の回答なんですけど? "Scripting.FileSystemObject" だとUTF-8を使えないので、"adodb.stream" を使います。それにつれて使うメソッドも変わります。
お礼
>No.7の補足に書いた以下ソースをutf-8対応で改修して頂けませんか。 すみません、No8で教えて頂いたソースを言いたかったのですが、 入力ミスでした。 No.9のようにbat内でvbsを作成するパターンと、 batからNo.8のようなvbsを呼び出すパターンを用意したいと思っています。 よろしくお願いいたします。
- notnot
- ベストアンサー率47% (4900/10359)
#2です。 #7のスクリプトでうまくいかないとすると、元のファイルの文字コードがシフトJIS以外のもの、例えばUnicodeになっていると思われます。 そうであると、補足でお書きのプログラムでも駄目かと。 試しに、 strNewText = Replace(strText, vbTab&vbCRLF, vbCRLF) でやってみて、駄目なら、Unicodeで処理するように下記のように変更します。 それでも駄目なら、そのファイルの文字コードが何であるかきちんと確認してください。 Const ForReading = 1 Const ForWriting = 2 Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile(入力ファイル名, ForReading, false, TristateTrue) strText = objFile.ReadAll objFile.Close strNewText = Replace(strText, vbTab&chr(0)&vbCR&chr(0)&vbLF&chr(0), vbCR&chr(0)&vbLF&chr(0)) Set objFile = objFSO.OpenTextFile(出力ファイル名, ForWriting, true, TristateTrue ) objFile.Write strNewText objFile.Close
お礼
再三のアドバイス、ほんとうにありがとうございます。 変換対象のテキストファイルの文字コードは UTF-8です。 教えていただいたソースで実行しても文字化けが発生していまいました。 他に対策があれば教えていただけたら非常に助かります。
- notnot
- ベストアンサー率47% (4900/10359)
#2です。 こんな感じですかね。ある程度バッチスクリプトが読み書き出来るのであれば、骨組み部分はバッチスクリプトで書くと、要件が少し変わった時に修正が楽です。下記はバッチの中でVBSファイルを作っています。 文字列処理は普通は正規表現とかを使いますけど、今回は「右端がタブなら取る」という簡単なのでシンプルにしました。 @echo off rem VBSファイルを作成する echo > tmp.vbs Do While Not WScript.StdIn.AtEndOfStream echo >>tmp.vbs str = WScript.StdIn.ReadLine echo >>tmp.vbs if Right(str,1) = vbTab then str = Left(str,Len(str)-1) echo >>tmp.vbs WScript.Echo str echo >>tmp.vbs Loop rem メイン処理 cscript //nologo tmp.vbs < "%~1" > "%~1.tmp" rem エラーなら終了 if errorlevel 1 exit /b 1 rem 後始末 del "%~1" tmp.vbs ren "%~1.tmp" "%~1"
お礼
ご回答ありがとうございます。 ソースを丸々コピーして cmdでtest.bat test.txtを実行したところ、 134項目→132項目になり、 文字化けが発生していました。 以下を作成してみたのですが、 ●●●に(タブ)(改行コード)、 ○○○に(改行コード)を設定して実行できないかと考えています。 vbsでの(タブ)と(改行コード)の指定方法はご存知でしょうか。 ++++++++++++++++++++++++++++++++++++ Const ForReading = 1 Const ForWriting = 2 Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile("C:wsh\Test.txt", ForReading) strText = objFile.ReadAll objFile.Close strNewText = Replace(strText, " \r\n", "\r\n") Set objFile = objFSO.OpenTextFile("C:wsh\Test.txt", ForWriting) objFile.WriteLine strNewText objFile.Close
補足
●と○に変換するのを忘れていました。。。 >strNewText = Replace(strText, "\r\n", "\r\n") → strNewText = Replace(strText, ●●●, ○○○)
- utakataXEX
- ベストアンサー率69% (711/1018)
一番楽チンなのは、UnixコマンドのWindows移植版(sed, awk, perlなど)を使う事だと思います。 上記で、Unix/Linuxのシェルでよくやるような正規表現を使った置換を行なえば、バッチに1~2行で済みます。 プロジェクト上、サードパーティ製品は使えない、と言うのであれば、マイクロソフトの Subsystem for UNIX-based Applications(SUA) を使えばOK。 (確か無償のはず) 「そんなわけのわからないものの導入は許可できない」となった場合、前回の補足の回答となりますが。 >・置換するテキストファイルをパラメータで渡す > (オンコーディングしない) 可能です。 (パラメータは環境変数経由で渡すのが一般的です) >・テキストファイル内の(タブ)(改行コード)を(改行コード)に置換 可能です。 正規表現が使用できます。 >・置換後のファイル名は置換前と同じ 可能です。 が、これは、そのように作り込めば、と言う意味です。 Javaを使われているならわかると思いますが、基本的なAPIに 「テキストファイルをオープンして一部変更してクローズする」 と言う機能はありません。(拡張的に実装されている場合はあるでしょうが) つまり、行を追記する場合を除いて、ファイル全体のリプレースしかありません。 (C/C++でもJavaでもWSHでもDOS拡張スクリプトコマンドでも同じ事です) だから、「ファイルのバックアップ→編集した内容をテンポラリファイルに出力→テンポラリをリネーム」などの手順が必要です。 >・batからWSHを呼び出す。 可能です。 と言うか、その使い方が一般的です。.vbs や .js を単体で普通は使いません。 call CScript //nolog xxxx.vbs 的な使い方をします。 上記に書いたとおり、パラメータは環境変数経由で渡すのが一般的なので、ここだけは慣れないとピンと来ないかもしれません。 (最近のだとできたかも?) >・batのパラメータに置換対象のファイル名を指定 可能です。 > WSHがパラメータで渡したファイルを変換 可能です。 今更な事を書いてしまいますが、末尾のタブ削除自体は、ファイル出力側で対応すべき話であって要件定義の詰めの甘さの問題ですよね。 そこを今から引っくり返してOK(出力側の改修工数が取れる)なら、それが、もっとも工数(追加の資産管理と言う意味での)が掛からなくてオールハッピーだと思います。
- kmee
- ベストアンサー率55% (1857/3366)
batを使う理屈がそれなら、Windows Script Host + VBscript / Javascript でも変わらないと思います。 ・BATを処理するコマンドプロンプトはWindowsに標準でインストールされているので、追加でインストールする必要はない →WSHも最近のWindows(98以降)なら標準でインストールされているので、追加でインストールする必要はない ・増える資産は~.batの1ファイル →増える資産は~.vbsまたは~.jsの1ファイル 多分、真意は ・BATを使うこと ではなく ・この程度の作業にJavaを使わないこと(管理ファイル(最低、.javaと.classの2つ)は増えるし、コンパイルは必要だし、実行環境の追加も必要だし...) ではないかと思います。
お礼
ご回答ありがとうございます。 了解しました。WHSで対応しようと思います。 WHS開発未経験なためアドバイスを頂きたいのですが、 以下可能でしょうか。 ・置換するテキストファイルをパラメータで渡す (オンコーディングしない) ・テキストファイル内の(タブ)(改行コード)を(改行コード)に置換 ・置換後のファイル名は置換前と同じ よろしくお願いいたします。
補足
入力ミスです。 WSHでした。 追加でお聞きしたいですが以下可能でしょうか。 ・batからWSHを呼び出す。 ・batのパラメータに置換対象のファイル名を指定 WSHがパラメータで渡したファイルを変換 よろしくお願いいたします。
- hitomura
- ベストアンサー率48% (325/664)
回答1で少々頓珍漢なことを言ったものです。 DOSプロンプトがそこまで進化しているとは知りませんでした。 ところで回答3への補足で > はい、今回どうしてもバッチでの対応でなければなりません。 と書かれてましたが、なぜバッチでの対応でなくてはならないのかお教えいただけないでしょうか。
補足
Javaで対応したいと思ったのですが、 プロジェクトで管理する資産を増やしたくないので batで対応しろとお達しが来たからです。 とはいうものの、テキストファイルに1行に130項目以上で4000行もあると 作成したbatだと文字化けが起きました。 ※130項目20行だと文字化けは起きず。 やはりbatでの対応は限界があるのでしょうか。
- kmee
- ベストアンサー率55% (1857/3366)
どうしてもバッチファイルでなければいけない理由はありますか? そうでないなら、WSHでVBSctipt/javascript とか、 Perl,Ruby,Python 等のテキスト処理に優れたスクリプト言語をインストールするとか、 sed, awk 等のunixコマンドのWindows移植版を使うとかが、安全で確実で早いと思うのですが。
補足
>どうしてもバッチファイルでなければいけない理由はありますか? はい、今回どうしてもバッチでの対応でなければなりません。
- notnot
- ベストアンサー率47% (4900/10359)
1の補足について。 タブはそのままエディターでタブを入れればいいです。 改行は指定出来ません。それ以前に、%line% には改行は含まれません。なので改行というより末尾のタブを削除するわけですが、末尾という指定は出来ないので、データに含まれない何かの文字を末尾の目印に使います。例えば、@ がデータに含まれないとすると、 set line=%%a を set line=%%a@ に変えて set l=%line:タブ@=% ↑タブの所にはエディタで実際にタブを入れてください。
お礼
ご回答ありがとうございます。 set l=%line:(タブ)(ハングル文字)=% で対応できました。 しかし、「データに含まれない何かの文字」というのが 運用上かなりグレーです。 他の方法はないでしょうか。
- hitomura
- ベストアンサー率48% (325/664)
DOSのバッチファイル以外の手段(正規表現が使えるテキストエディタを使って置換するとか、VBScriptで置換用のスクリプトを書くとか)を使いましょう。 UNIX系のシェルスクリプトでは簡単に除去できますが、DOSのコマンドプロンプトはファイルの内容を編集する機能を持たないため不可能です。
補足
補足です。 以下を作成しました。 ●●●に(タブ)(改行コード)を指定、 ○○○に(改行コード)を指定できれば、やりたいことが出来そうです。 が、タブ と 改行コード の指定の方法が分かりません。 よろしくお願いします。 ++++++++++++++++++++++++++++++++++++++++++++++ @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行下の ●●●を○○○に変換する。 set l=%line:●●●=○○○% echo %l%>>%fname% goto :EOF :end
お礼
ご回答ありがとうございます! また、情報不足のまま質問して申し訳ありません。 上記ソースでやりたいことができました! ほんとうにありがとうございます。 度々のお願いで申し訳ないのですが、 No.7の補足に書いた以下ソースを utf-8対応で改修して頂けませんか。 明日プロジェクトリーダに batに対象ファイルを引数として渡し末尾のタブを削除する方法と、 batからvbsを呼びだし対象ファイルの末尾のタブを削除する方法を提案してみたいのです。 よろしくお願いいたします。 ++++++++++++++++++++++++++++++++++++ Const ForReading = 1 Const ForWriting = 2 Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile("C:wsh\Test.txt", ForReading) strText = objFile.ReadAll objFile.Close strNewText = Replace(strText, "\t\n\r", "\n\r") Set objFile = objFSO.OpenTextFile("C:wsh\Test.txt", ForWriting) objFile.WriteLine strNewText objFile.Close