
master.csvの内容
11111,eeeeee,55555
for /f "delims=" %%A in (master.csv) do call :sub1 "%%A"
del master.csv
ren master6.csv master.csv
goto :eof
:sub1
set "LINE=%~1"
echo %LINE:,=2C%>>master6.csv
以上のようにカンマを2Cに変換し、改行コード(CR)(LF)を0D0Aに変換したいのですが、
どうしたらよいでしょうか?
また、同時に実行することは可能でしょうか?
No.4ベストアンサー
- 回答日時:
>・ID_before"の値が "0001010114100DD800" をunhexして、CSVファイルに出力したものをバイナリーエディターで見ると"01010114100DD85C30"となってしまうのです。
自分の環境では、まったく同じにはなりませんでしたが、確かに似たような状態になりますね。
(バイナリ値の前後に \0 が付くんですね)
で、正直に申し上げて、これをどうやって回避するかは、自分にはわかりかねます。
何度も言うように、バイナリをこの方法でやり取りするところに無理があるのであって。
CSVにバイナリを入れる事自体がイレギュラーなので、繰り返しになりますが、私なら最初からこうします。
(前の回答の繰り返しです)
↓
SQL文は以下でCSVを作成
SELECT ID_before,CODE_AFTER,NAME_AFTER FROM work1 into outfile "C:/master2.csv" fields terminated by ",";
↓
CSVをバイナリだけ除いて移行先のテーブルにインポート
↓
で、多分「それじゃ移行先でバイナリが入れられないじゃないか」と思われるでしょうが、「だから!」そこは移行した先でバイナリにするんですって!
↓
(例) UPDATE ikou SET ID_after = unhex(ID_before) WHERE ID_after IS NULL;
今、自分の環境でサクッと試してみましたが、何の苦労もなく入れられました。
現在、実装されていると構成が変わるので、手戻りにはなりますが、「CSVにバイナリを入れる」事に拘泥して、この後わんさか出てくる諸問題を考えると、質問者様も上司も顧客もオールハッピーになるには、これしかありません!
まあ、ひょっとしたら回避方法を知っている識者がMySQLカテにいるかもしれませんけどね。
そこは、またあちらで聞いてみてはどうでしょうか?
>・CSVに出力したものをバイナリーエディターでみると、改行コードが、CrLF にしたいのですが、LFだけしか表示されません。
こちらは私の環境でもそうなります。
これは mysql.exe の仕様っぽいですね。
ただ、移行先でLFのままでも問題がなければ、それでもOKと思いますけど。
移行先の仕様上、または要件定義上、CRLF以外は許容できないのであれば前の回答で提示したVBScriptを改造して、「LF→CRLF」にファイル丸ごと置換するようなものを作って間に噛ませてやればよいと思います。
(そこはご自身でお願いしますね)
>・CSVに出力したものをバイナリーエディターでみると、最後の行に’1A’とバイナリーエディターで表示されてしまうのです。
ああ、失礼。そのSUB(0x1A)ですね。
こちらは、私の環境では再現できなかったですが、想像は付きます。
多分結果のCSVに、COPYコマンドでヘッダー行を付けているのではないですか?
その場合は、末尾に0x1Aが付くのはMS-DOS時代からの仕様です。
(ハイ、そこのオジサン連中はニヤニヤしない!w)
copy Aファイル + Bファイル 最終ファイル
ではなく
copy /b Aファイル + Bファイル 最終ファイル
とすれば、末尾の0x1Aは消えます。
この回答への補足
UPDATE ikou SET ID_after = unhex(ID_before) WHERE ID_after IS NULL;
を行うと、一度うまくいあったのですが、SQLを投げる時に、character はしないほうがよいのですかね?
ECHO SET character SET sjis;>create0_sql.sql
ちなみにUPDATE して格納するテーブルの定義は型は関係ありますか?
No.5
- 回答日時:
ささっと要点だけ。
> UPDATE ikou SET ID_after = unhex(ID_before) WHERE ID_after IS NULL;
> を行うと、一度うまくいあったのですが、SQLを投げる時に、character はしないほうがよいのですかね?
文字コード関連のSET文は、今回の場合に関しては関係ないです。
日本語の項目があって、それを表示したいならSETすればよいし、英数字しか扱わないのであれば、SETする必要無し。
> ちなみにUPDATE して格納するテーブルの定義は型は関係ありますか?
これは関係ありますよ。
バイナリを入れるのだから、それ用の型で定義する必要があります。
因みに私が、この質問に答えるのに作成したテーブルは以下の通りです。
(主キーやリレーションは一切考慮していません)
create table work1
(
ID_before varchar(18),
CODE_AFTER varchar(10),
NAME_AFTER varchar(50)
);
create table ikou
(
ID_before varchar(18),
ID_after varbinary(9),
update_date timestamp
);
今回のような小さいバイナリを入れるのであれば、VARBINARYを使用します。
定義する場合は、上記のように VARBINARY(n) で定義するか、VARCHAR(n) CHARACTER SET binary で定義します。
※IDmの長さは原則的に不変なはずなので、BINARY(n)=CHAR(n) CHARACTER SET binary の方が適当だったかな?
No.3
- 回答日時:
#1、2 です。
正直、今回の#2の補足質問の内容は、私には理解できません。
>"ID_before"の値が "0001010114100DD800" をunhexすると、"01010114100DD85C30"
work1.ID_beforeに入っているのは文字列ですか?バイナリですか?
文字列で 0001010114100DD800 になっているなら、unhexしたら文字列"01010114100DD85C30"にはなり得えません。
(人間には読めない値になります)
これがFelicaのIDmだとしたら、何故(Felicaチップにアクセスする時以外にも)バイナリ値でやり取りしないといけないのかが、相変わらずわからないのですが、ええ、そこはいいです。もう私が折れましょうw
しかし、折れるに折れられない部分があります。他の回答でも書いた事ですが、
「何で、unhexしたバイナリ値をCSVに入れるのかなぁ?」
バイナリに何が入るかは不定ですよね?
たまたまカンマ(と同じASCIIコード)や Cr(と同じASCIIコード)や Lf(と同じASCIIコード)が入っていたらどうなります?
その事の可否はフェリカネットワークスやソニーが決める事であって、私達使用する側ではどうあっても制御できませんよね。
「たまたまお客様のIDmには制御文字が含まれておりますので、取り込めませんでした。お諦めください」
って言いますか?
「何故バイナリの先頭と末尾が変わったか?」について、はっきりと特定はできませんが、バイナリとテキストが混在したCSVからバイナリだけ抜いて、移行先に上手い事、格納するなんて、普通の mysql.exe や他のクライアントツールではそもそもが無理ですよ。
うまく行く事もあるでしょうが、うまく行かなかった時にリカバリーする方法がありません。
どうしても、それが必要なら C言語 か何かでクライアントツールを作るしかありません。
で、とにかく私がお薦めする、ソリューションとしてはですね。繰り返しになりますが。
「CSVにバイナリを入れるのは諦める」
これしかありません。
バイナリを扱いたい、と言うのは、ええ、くどいけど折れますよ。
でもCSV渡しで、確実にバイナリ値を移行したいなら、HEXした文字列で渡すしかありませんよ、普通。
【移行元DB】
IDmがHEX表記の文字列で格納されている(で合ってますよね?)
↓
CSVに『unhexせず』そのまま格納(ここが重要!)
↓
【移行先DB】
IDmは文字列とバイナリ両方のカラムを持っている(でいいのかな?)
↓
文字列のカラムはそのままインポートなりインサートなり、すればよい
↓
バイナリのカラムの方は(ここで初めて)unhexしたものを入れればよい
例えば
update kekka_table set idm_bin = unhex(idm_mojiretu) where idm_bin is null
とかね。
あ、これが20バイト足らずなので、上記のように書いていますが、バイナリの大きさが数MB~GBクラスになったら、さすがにそんな事はしませんよ。
その場合は、LOB(ラージバイナリオブジェクト)になるので、そもそも扱いが違います。
>また、改行コードが、CrLF にしたいのですが、LFだけしか認識しません。
どこの改行コード?認識しないとは誰(何)が?
>最後にSUBが入ってしまいます。
何の最後に?CSVの最後に"SUB"と言う文字列が入る、と言う事ですか?
最後はちょっと苦言。
>確認したところ、上記の変換はしなくてよかったのですが、
むむむ。
「本当にこれで要件満たせるの?」と念押しした上での#2の回答だったんですけど。。。
失礼を承知で言ってしまいますが、少し「泥縄」と言うか「後手後手」過ぎませんか?
#1 で書いた、「わざわざ物凄く遠回りなシステム構成/実装」と感じる部分が、質問者様ご自身に起因するものなのか、上司やお客さんの無茶ぶりによるものなのか、私には知る由もありませんが、多分、このままだと長大な質問ツリーがシステムリリースまで(リリース後の運用フェーズでも)続くような気がします。
確実に言える事は、バイナリやキャラクタセットについての扱いを質問者様ご自身があまり理解されていないようで、そのために質問や、実装方法も、なんとなくトンチンカンなものになってしまっているようです。
ともあれ、乗りかかった船。もうここまで来たら、できる限りの回答はしますので、補足をお願いします。
(私自身の業務に支障を来たさない範囲でですがwww)
この回答への補足
・ID_before"の値が "0001010114100DD800" をunhexして、CSVファイルに出力したものをバイナリーエディターで見ると"01010114100DD85C30"となってしまうのです。
・CSVに出力したものをバイナリーエディターでみると、改行コードが、CrLF にしたいのですが、LFだけしか表示されません。
・CSVに出力したものをバイナリーエディターでみると、最後の行に’1A’とバイナリーエディターで表示されてしまうのです。
No.2
- 回答日時:
#1 です。
> インストールできない環境なので、
> BATからVBScriptで処理するには、どうしたらよいのでしょうか?
この補足があると言う事は、やりたい事はこれで間違いない、と言う事ですね。
(何か釈然としないけど、まあ、そこまで私がどうこう言える立場でもないので。。。)
実装に手間のかからない方法で書きます。
パスやターゲットの文字列等は引数にして汎用的に作る事も可能ですが、固定にします。
(自分が面倒臭いだけw)
まず、以下のVBScriptを replace_crlf.vbs として保存してください。
ここから↓↓↓↓
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim vbCrLF
Dim fso, f
Dim ifile
Dim strBuf
' 改行変数
vbCrLF = chr(13) & chr(10)
' ファイル名
ifile = "master.csv"
' ファイルオープン
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(ifile, ForReading)
' ファイルの内容をReadAllで変数に格納
strBuf = f.ReadAll()
' ファイルクローズ
f.Close
' カンマを"2C"に置換+CRLFを"0D0A"に置換(ファイル丸ごと)
strBuf = Replace(strBuf, ",", "2C")
strBuf = Replace(strBuf, vbCrLF, "0D0A")
' 結果表示
WScript.Echo strBuf
ここまで↑↑↑↑
ReadAll で丸ごと取得した変数を丸ごと2回置換し、標準出力に一気に吐き出す、と言う超手抜き版です。
CSVの件数がかなり多い(または横列が長大の)場合は結構時間がかかります。
(1)エラー等の取り回しを考えても、Readline で1行ずつ処理した方がいいでしょう。
(2)結果としては改行の無い長大な1行データになりますが、この構成で横列が何バイトまで出力可能なのかは、私にもわかりません。
Echoのリダイレクトではなく、出力ファイルを定義して改行無しのWriteで追記していく方が確実です。
(3)最初に書いたとおり汎用的なパラメータ取得にはしていません。
上記3点はご自身の自助努力でお願いします。
上記VBSを使って、前の回答で使ったバッチを少し弄って、こんな感じにします。
@echo off
REM FOR文使わず楽ちんバージョン(VBS版)
REM カンマを"2C"に置換+CRLFを"0D0A"に置換(ファイル丸ごと)
call cscript //nologo replace_crlf.vbs > master6.csv
del master.csv
ren master6.csv master.csv
それと、重要な事を書き忘れましたが、今書かれているバッチは、パスを意識した作りになっていませんよね。
これも老婆心から補足しておきます。
本番への適用が初回の1回~数回だけの移行処理で、実行も手動でするなら、このままで問題ありません。
しかし、もし、タスクスケジューラで毎日定期的に起動するのであれば、このままでは実行時にエラーになるので、使用するコマンド(DOSコマンドは除外)やファイル名はフルパスで記述するようにしてください。
(システムパスが通っている場合でもそうするのがセオリーです)
これは、Unix/Linuxなどで cron で処理する場合も同様です。
でも。。。やっぱり構成や基本設計から見直した方がいいんじゃないかなぁ。
ここの識者の皆さんも(わざわざ言わないだけで)同意見だと思うけど。
あの(CSVではない)CSVファイルをどうやって運用していくつもりなのか、気になる。。。
この回答への補足
何度もすみません。
確認したところ、上記の変換はしなくてよかったのですが、
以下のSQLを発行してCSVに出力するのですが、
DBに格納されている"ID_before"の値が "0001010114100DD800" をunhexすると、"01010114100DD85C30"
と変換されてしまうのですが、どうしてでしょうか?
また、改行コードが、CrLF にしたいのですが、LFだけしか認識しません。
あた、最後にSUBが入ってしまいます。
どうしたら、よいでしょうか?
SELECT unhex(ID_before),CODE_AFTER,NAME_AFTER FROM work1 into outfile "C:/master2.csv" fields terminated by ",";>>create3_sql.sql
No.1
- 回答日時:
まず、ご質問の回答としては。
Windows(DOS)のコマンドで、カンマは'2C'に置換できます。
(既に質問者様ご自身で実装されている通りです)
しかし、改行(CRLF)は置換できません。
制御文字のすべてがダメかと言うと、微妙にそうでもないんですが、改行については、どうやっても無理です。
findstrの正規表現にも改行を捕捉する術はありません。
VBScript や Windows PowerShell で Replace するとか、jperl や tr(Unixの置換コマンドのDOS移植版)などで、正規表現で改行を捕捉して置換するとかになります。
VBScriptなら何もインストールする必要がなくて済みますが、データが大量だと結構時間がかかるので、個人的には jperl や tr の使用をお薦めします。
(新規にユーティリティ類をインストール可能なら)
jperl を使った例で、質問者様のバッチを少し弄ると以下のようになります。
@echo off
for /f "delims=" %%A in (master.csv) do call :sub1 "%%A"
REM 改行(CRLF)を文字列"0D0A"に置換(ファイル丸ごと)
jperl -pe "s/\n/0D0A/g" < master6.csv > master6_tr.csv
REM ※リネームファイルを変更した点に注意!
del master.csv
del master6.csv
ren master6_tr.csv master.csv
goto :eof
:sub1
set "LINE=%~1"
echo %LINE:,=2C%>>master6.csv
:eof
これでご希望の事はできるのですが、こうなってしまうと、むしろ FOR文を使わず、jperlだけを使った方が楽ちんで速い、と言う事になります。
以下を見てわかるとおり、バッチ自体も非常にシンプルになります。
@echo off
REM FOR文使わず楽ちんバージョン
REM カンマを"2C"に置換+CRLFを"0D0A"に置換(ファイル丸ごと)
jperl -pe "s/,/2C/g" < master.csv | jperl -pe "s/\n/0D0A/g" > master6.csv
del master.csv
ren master6.csv master.csv
さて、回答としては以上なのですが、また少しおせっかいな事を書きます。
これで業務要件としては満たせますか?
CSVのカンマと改行だけ"2C"と"0D0A"に置換する意味がわからないのです。
因みに、例えば、2行あったら結果は以下のようになります。
1111,aaaaa,あ
2222,bbbbb,い
↓
11112Caaaaa2Cあ0D0A22222Cbbbbb2Cい0D0A
この master.csv を受け取る側は、この内容で何ができるんでしょうか?
既にCSVではなくなっているし、改行も無いので通常のWindowsやLinuxのアプリケーションではあまり使わないフォーマットと言えます。
(しいて言えば、汎用機?それにしたって無理がある)
すべてのカラムがHEXになっているなら、まだ何となくわかりますけど。
(いや、何となくですけど)
何かこの、やり取りさせていただいても、「普通なら単純にできる事を、わざわざ物凄く遠回りなシステム構成/実装にしているのではないか?」と受け取れる内容なんですよ。
まあ、「これこそがやりたい事だ」と言われれば大きなお世話なんですが。。。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) ユーザーフォーム「frm_基本❶」を立ち上げると新規で入力する行数を右下のNoとして表示しています。 1 2023/03/16 19:02
- Visual Basic(VBA) ユーザーフォームの表示を追加したい 2 2023/03/26 23:18
- クレジットカード Masterカードでの支払いのポイントが5分の1に変更 なぜ? 2 2022/10/16 01:13
- Visual Basic(VBA) 複数のcsvファイルをExcelに一括変換したい 2 2023/03/03 12:44
- 軍事学 帆船時代のsecond masterの訳し方を教えてください。航海長(master)の次席で、船倉の 3 2022/09/21 14:14
- C言語・C++・C# 並列プログラミングのπ計算について 1 2022/07/16 22:30
- 英語 CHSL, a minimally invasive sinus lift surgery is v 2 2023/01/16 11:55
- PHP htmlで複数の個数入力欄を表示させるには 1 2022/09/20 03:11
- Windows 10 Windowsのバッチファイルで正規表現の置換方法について… 4 2022/12/09 16:00
- その他(プログラミング・Web制作) pythonのこのエラーがわかりません 3 2022/11/16 14:54
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Macで簡単に改行を解除したい
-
メモ帳での一括たて列選択
-
【文字コード】コピー&ペース...
-
英語版WindowsでのCSVファイル...
-
windowsのメモ帳からlinuxへコピペ
-
RedHatで使えるエディタ
-
ブラウザのテキストをコピーし...
-
【Redhat】SJISにおける文字化け
-
illustrator cs2「均等配置(最...
-
メモ帳での改行
-
ubuntuでテキストファイルが開...
-
au 携帯のメール(vMessage, .v...
-
ルビ付きのワード文書をMacでテ...
-
ViエディタとVimエディタの違い...
-
LinuxMintで,Windows時代に作成...
-
WinとMacで互換性のあるテキス...
-
Linuxで書いたプレーンテキスト...
-
ファイル名の付け方(中央揃え)
-
ソースが文字化けして困ってます。
-
XMLの表示文字化け
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Macで簡単に改行を解除したい
-
メモ帳での一括たて列選択
-
LinuxMintで,Windows時代に作成...
-
【文字コード】コピー&ペース...
-
RedHatで使えるエディタ
-
ドラッグ&コピー→デスクトップ...
-
WinとMacで互換性のあるテキス...
-
windowsのメモ帳からlinuxへコピペ
-
au 携帯のメール(vMessage, .v...
-
MS-DOSテキストファイルっ...
-
アイコンの名前の改行
-
ubuntuでテキストファイルが開...
-
メモ帳の出力形式
-
Linuxで書いたプレーンテキスト...
-
XMLの表示文字化け
-
ブラウザのテキストをコピーし...
-
illustrator cs2「均等配置(最...
-
FTP 文字化け
-
バッチ処理での改行出力
-
テキストで特定の文字列を含む...
おすすめ情報