アプリ版:「スタンプのみでお礼する」機能のリリースについて

DOSバッチ開発で困っています。

あるテキストファイル(DBから出力したタブ区切りのファイル)に
n行データが入っています。
1行につき133項目もっています。
各行の最後の項目は必ずタブがあります。
この末尾のタブのみ削除してファイルを置き換えたいです。
バッチ開発経験が浅いため、うまく作成ができません。
よろしくお願いいたします。

A 回答 (10件)

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

補足日時:2011/03/05 11:36
    • good
    • 0

1の補足について。


タブはそのままエディターでタブを入れればいいです。

改行は指定出来ません。それ以前に、%line% には改行は含まれません。なので改行というより末尾のタブを削除するわけですが、末尾という指定は出来ないので、データに含まれない何かの文字を末尾の目印に使います。例えば、@ がデータに含まれないとすると、

set line=%%a を set line=%%a@
に変えて
set l=%line:タブ@=%

↑タブの所にはエディタで実際にタブを入れてください。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
set l=%line:(タブ)(ハングル文字)=%
で対応できました。

しかし、「データに含まれない何かの文字」というのが
運用上かなりグレーです。

他の方法はないでしょうか。

お礼日時:2011/03/05 18:20

どうしてもバッチファイルでなければいけない理由はありますか?



そうでないなら、WSHでVBSctipt/javascript とか、 Perl,Ruby,Python 等のテキスト処理に優れたスクリプト言語をインストールするとか、 sed, awk 等のunixコマンドのWindows移植版を使うとかが、安全で確実で早いと思うのですが。

この回答への補足

>どうしてもバッチファイルでなければいけない理由はありますか?
はい、今回どうしてもバッチでの対応でなければなりません。

補足日時:2011/03/05 18:51
    • good
    • 0

回答1で少々頓珍漢なことを言ったものです。


DOSプロンプトがそこまで進化しているとは知りませんでした。

ところで回答3への補足で
> はい、今回どうしてもバッチでの対応でなければなりません。
と書かれてましたが、なぜバッチでの対応でなくてはならないのかお教えいただけないでしょうか。

この回答への補足

Javaで対応したいと思ったのですが、
プロジェクトで管理する資産を増やしたくないので
batで対応しろとお達しが来たからです。
とはいうものの、テキストファイルに1行に130項目以上で4000行もあると
作成したbatだと文字化けが起きました。
※130項目20行だと文字化けは起きず。

やはりbatでの対応は限界があるのでしょうか。

補足日時:2011/03/06 10:34
    • good
    • 0

batを使う理屈がそれなら、Windows Script Host + VBscript / Javascript でも変わらないと思います。



・BATを処理するコマンドプロンプトはWindowsに標準でインストールされているので、追加でインストールする必要はない
→WSHも最近のWindows(98以降)なら標準でインストールされているので、追加でインストールする必要はない

・増える資産は~.batの1ファイル
→増える資産は~.vbsまたは~.jsの1ファイル


多分、真意は
・BATを使うこと
ではなく
・この程度の作業にJavaを使わないこと(管理ファイル(最低、.javaと.classの2つ)は増えるし、コンパイルは必要だし、実行環境の追加も必要だし...)
ではないかと思います。

この回答への補足

入力ミスです。
WSHでした。

追加でお聞きしたいですが以下可能でしょうか。
・batからWSHを呼び出す。
・batのパラメータに置換対象のファイル名を指定
 WSHがパラメータで渡したファイルを変換


よろしくお願いいたします。

補足日時:2011/03/06 12:06
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
了解しました。WHSで対応しようと思います。

WHS開発未経験なためアドバイスを頂きたいのですが、
以下可能でしょうか。
・置換するテキストファイルをパラメータで渡す
 (オンコーディングしない)
・テキストファイル内の(タブ)(改行コード)を(改行コード)に置換
・置換後のファイル名は置換前と同じ

よろしくお願いいたします。

お礼日時:2011/03/06 12:01

一番楽チンなのは、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(出力側の改修工数が取れる)なら、それが、もっとも工数(追加の資産管理と言う意味での)が掛からなくてオールハッピーだと思います。
    • good
    • 0

#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"

この回答への補足

●と○に変換するのを忘れていました。。。
>strNewText = Replace(strText, "\r\n", "\r\n")
 → strNewText = Replace(strText, ●●●, ○○○)

補足日時:2011/03/06 18:15
    • good
    • 0
この回答へのお礼

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

ソースを丸々コピーして
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

お礼日時:2011/03/06 18:13

#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
    • good
    • 0
この回答へのお礼

再三のアドバイス、ほんとうにありがとうございます。

変換対象のテキストファイルの文字コードは
UTF-8です。

教えていただいたソースで実行しても文字化けが発生していまいました。

他に対策があれば教えていただけたら非常に助かります。

お礼日時:2011/03/06 19:30

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プログラム内のでエラー処理は手抜きです。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます!
また、情報不足のまま質問して申し訳ありません。
上記ソースでやりたいことができました!
ほんとうにありがとうございます。

度々のお願いで申し訳ないのですが、
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

お礼日時:2011/03/06 21:14

>No.7の補足に書いた以下ソースをutf-8対応で改修して頂けませんか。




それが、No9の回答なんですけど?

"Scripting.FileSystemObject" だとUTF-8を使えないので、"adodb.stream" を使います。それにつれて使うメソッドも変わります。
    • good
    • 0
この回答へのお礼

>No.7の補足に書いた以下ソースをutf-8対応で改修して頂けませんか。
すみません、No8で教えて頂いたソースを言いたかったのですが、
入力ミスでした。

No.9のようにbat内でvbsを作成するパターンと、
batからNo.8のようなvbsを呼び出すパターンを用意したいと思っています。


よろしくお願いいたします。

お礼日時:2011/03/06 23:17

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

このQ&Aを見た人はこんなQ&Aも見ています