こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

DOSプロンプトのテキストファイルから取得したフィールドがデータ無しの場合の認識方法

CSVファイルから各フィールドを取得し、なにも入っていない場合は固定値を入れると言う処理を、DOSのコマンドプロンプトによるバッチで行ってほしいと言うユーザ要望に答えなくてはなりません。

【入力ファイル】
<<AAA.csv>>
aaa,,bbb,,ccc,ddd
iii,jjj,kkk,lll,mmm,nnn
eee,,fff,,ggg,hhh

このAAA.csvを入力情報にして、
カンマ区切りの何も入っていないフィールドを認識し、
上記ファイルで言うと、
各行の2項目に何も入っていない場合は222を、
各行の4項目に何も入っていない場合333を入れる、
と言う処理を作る必要があります。

上記に説明した処理での出力結果は以下の様になります。

【出力ファイル】
<<BBB.csv>>
aaa,222,bbb,333,ccc,ddd
iii,jjj,kkk,lll,mmm,nnn
eee,222,fff,333,ggg,hhh

forやsetを駆使してフィールドの取得や変換は出来たのですが、
取得したフィールドに何も入っていなかった場合に固定値を入れる処理で行き詰っています。

何か良い方法があれば教えてください。

ちなみに入力や出力ファイルはタブ区切りのTSVファイル形式の場合もあります。

又環境は、銀行のサーバで実装するのでフリーソフトはもちろんparlやWSH等のインストールも許されていない為、DOSプロンプトコマンドによるバッチ処理のみで行う必要があります。

宜しくお願いします。

投稿日時 - 2008-08-10 04:22:28

QNo.4240650

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

7人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.6

こんにちは。

> 又環境は、銀行のサーバで実装するのでフリーソフトはもちろんparlやWSH等のインストールも許されていない為、DOSプロンプトコマンドによるバッチ処理のみで行う必要があります。

ANo.1, ANo.2 と類似の問いかけとなりますが、こうした制約がどこからくるものなのか、ユーザに問い合わせて正確な把握にトライされてはいかがでしょうか。

(回答者のコメント)

回答者も何度かサーバに持ち込む場合の制約を課せられた経験があります。ただ、大概は素性の知れないプログラムがシステムにもぐりこんだ際の様々なリスクにどう処するか、という観点がほとんどです。素性が知れている、とはどういう意味か、回答者は、それが使用するライブラリがわかっていて、アルゴリズムも(ソースコードから)わかっていて、それがどんな挙動を示すか見通せている、という意味で用いています。

ユーザにそのことを理解してもらい、リスクを分析/評価し、未来起こることに腹をくくる決断をユーザがするのであれば、ユーザは DOS プロンプト (cmd.exe) だけで実装せよ、という制約をもう少し緩められるのでは?? と回答者は推測します。もちろん、リスクの分析/評価に際して会社の方針をすべてに優先すべき場合もあります。それゆえ、ユーザにその考え方はどこから来ているのかを確認してみては? とコメントしました。

投稿日時 - 2008-08-10 17:47:02

補足

色々とご意見有り難うございます。
ただあくまでもバッチでと言う要望なのでANo.1でもコメントしたとおり、まだギブアップせずまずは可能なのかを調査している段階です。
またここではその様な議論をすると言うよりバッチで可能かどうかの事実関係が知りたいです。

投稿日時 - 2008-08-11 02:05:17

ANo.5

#4です。失礼しました。質問を取り消します。

投稿日時 - 2008-08-10 08:39:02

ANo.4

処理をするプログラムの実体は、perlとかC言語とかで実装し、それをDOSのコマンドプロンプトのバッチから呼び出すのが、ふつうだと思うのですが、それではダメなのでしょうか?

投稿日時 - 2008-08-10 08:36:13

補足

だめです。あくまでもバッチでとの要望なので。
理由はここで議論すべきことではないのでやめます。

投稿日時 - 2008-08-11 02:03:04

ANo.3

for文で分解すると連続したデリミタが一つの区切りに扱われてしまって空フィールドが判断できない、という感じでしょうか?
(ハズしていたら以下は無視してください)

かなり強引な気がしますが以下のようなバッチではダメでしょうか?
(遅延環境変数展開を使っているのでcmd /V:ONで起動する必要があります)
@echo off
for /F "delims=" %%L in ( %1 ) do call :Sub "%%L"
goto :EOF

rem 行単位の処理
:Sub
setlocal
rem 先頭と末尾の引用符除去
set LINE=%1
set LINE=%LINE:~1,-1%
rem カンマ,が複数連続している場合にスペースを挟む
:Loop
set LINE=%LINE:,,=, ,%
echo %LINE% | find ",," > null
if %ERRORLEVEL% EQU 0 goto :Loop
rem カンマ,区切りに分解してスペース1コならばフィールド番号に置き換えて連結
for /F "tokens=1-6 delims=," %%M in ( "%LINE%" ) do (
set RESULT=
if "%%M"==" " (set RESULT=111) else (set RESULT=%%M)
if "%%N"==" " (set RESULT=!RESULT!,222) else (set RESULT=!RESULT!,%%N)
if "%%O"==" " (set RESULT=!RESULT!,333) else (set RESULT=!RESULT!,%%O)
if "%%P"==" " (set RESULT=!RESULT!,444) else (set RESULT=!RESULT!,%%P)
if "%%Q"==" " (set RESULT=!RESULT!,555) else (set RESULT=!RESULT!,%%Q)
if "%%R"==" " (set RESULT=!RESULT!,666) else (set RESULT=!RESULT!,%%R)
echo !RESULT!
)
endlocal
goto :EOF

上記のままだと
・フィールド数が固定
・スペースが複数入っている場合は空フィールドとして扱われない
・%文字が入っていた場合が考慮されていない
・デリミタはカンマのみ
といった問題がありますが参考になれば。

#でもこれだけのことをするならきちんと言語を使って加工するべきな気がします

投稿日時 - 2008-08-10 07:42:16

補足

ありがとうございます。
ただご教示頂いた例ですと行の最初のフィールドと最後のフィールドが変換されない様です。
例えば入力ファイルが、
<<CCC.csv>>
,,bbb,,ccc,ddd
iii,jjj,kkk,lll,mmm,nnn
eee,,fff,,ggg,

の様に、
1行目の最初と3行目の最後のフィールドになにも入っていなかった場合、
出力ファイルをご教示頂いたバッチの変換で、
<<DDD.csv>>
111,222,bbb,333,ccc,ddd
iii,jjj,kkk,lll,mmm,nnn
eee,222,fff,333,ggg,666

と行った様に、
一行目の最初のフィールドは111に、
三行目の最初のフィールドは666に変換出来る様にしたいです。

もうすこしです。
有り難うございます。

投稿日時 - 2008-08-10 22:47:45

お礼

おかげさまで補足に書いた内容も解消できました。
頂いた例を元に下記の様に作成しました。
なお自動ジョブによりこのバッチが起動する様になるため、
遅延環境変数展開を使用しない方法に変えました。

【入力ファイル】
<<CCC.csv>>
,,bbb,,ccc,ddd
iii,jjj,kkk,lll,mmm,nnn
eee,,fff,,ggg,

【実行結果ファイル:EEE.csv】
111,222,bbb,444,ccc,ddd
iii,jjj,kkk,lll,mmm,nnn
eee,222,fff,444,ggg,666

【実行したバッチファイル】
echo off
for /F "delims=" %%L in ( CCC.csv ) do call :Sub "%%L" >>DDD.csv
for /F "tokens=1-6 delims=," %%a in (DDD.csv) do (
set A=%%a
set B=%%b
set C=%%c
set D=%%d
set E=%%e
set F=%%f
call :sub0
) >> EEE.csv
goto :EOF

rem 行単位の処理
:Sub
setlocal
rem 先頭と末尾の引用符を除去し、カンマ,に置換え
set LINE=%1
set LINE=,%LINE:~1,-1%,
rem カンマ,が複数連続している場合にスペースを挟む
:Loop
set LINE=%LINE:,,=, ,%
echo %LINE% | find ",," > null
if %ERRORLEVEL% EQU 0 goto :Loop
echo %LINE%
del null
goto :EOF

:sub0
if "%A%"==" " set A=111
if "%B%"==" " set B=222
if "%C%"==" " set C=333
if "%D%"==" " set D=444
if "%E%"==" " set E=555
if "%F%"==" " set F=666
echo %A%,%B%,%C%,%D%,%E%,%F%
goto :EOF

教えていただいた、「カンマ,が複数連続している場合にスペースを挟む」
の処理がポイントでした。
そこに最初と最後にもカンマ,を付けたら出来ました。
有難う御座いました。

投稿日時 - 2008-08-11 03:47:07

ANo.2

>>環境は、銀行のサーバで実装するのでフリーソフトはもちろんparlやWSH等のインストールも許されていない為、DOSプロンプトコマンドによるバッチ処理のみで行う必要があります。

「無理です!」って答えたほうがいいと思います。できるというなら、「やり方を教えてください」と言いましょう。

投稿日時 - 2008-08-10 05:19:01

補足

客に出来ないかと頼まれているのでとりあえずがんばって調べている最中です。

投稿日時 - 2008-08-11 02:01:44

ANo.1

> 又環境は、銀行のサーバで実装するのでフリーソフトはもちろん
> parlやWSH等のインストールも許されていない為、DOSプロンプト
> コマンドによるバッチ処理のみで行う必要があります。

ここが気になるのですが通常、サーバならPerlは標準インストール
されているはずですし、OSがWindowsならWSHはOSの一部ですので
よほど特殊な環境でない限り使用できるはずです。

あと、ローカルで処理してサーバにアップするという方法もあります
けどサーバで処理したいということなのでしょうか。

投稿日時 - 2008-08-10 05:06:49

補足

日々出力されるファイルに対し、サーバ上のバッチ処理で自動化する必要があると言うことです。

投稿日時 - 2008-08-11 00:03:15

あなたにオススメの質問