3

私の問題を説明させてください。大量のデータを含むExcelからエクスポートされたcsvファイルがあります。ファイルの最初の行にはタイトルがあり、2番目の行には列見出しがあります。そのファイルから2つの列(2番目と3番目)だけを抽出し、それらを1つの列に配置して、出力を別のファイルに送信する必要があります。

例:

Title
colA , colB , colC , colD ,...
abc  , def  , ghi  , jkl  ,...
abc  , def  , ghi  , jkl  ,...
abc  , def  , ghi  , jkl  ,...
abc  , def  , ghi  , jkl  ,...

問題は、csvパーサーが、-()@文字を含む文字列を含む行に出会うと失敗することです。(ループはそれらを区切り文字として扱うので、毎回範囲外エラーが発生します)。

これが私がすでに持っているものです。

@Echo off & setlocal EnableExtensions
setLocal EnableDelayedExpansion

REM creating and clearing files
copy /y NUL C:\list1.csv >NUL
copy /y NUL C:\list1_tmp.csv >NUL
copy /y NUL C:\exportedColumns.csv >NUL
copy /y NUL C:\Result.txt >NUL

set Result=C:\Result.txt
set Source=C:\sourcelist.csv
set list1=C:\list1.csv
set list1_tmp=C:\list1_tmp.csv
set expCol=C:\exportedColumns.csv

REM skip 1st two lines from source file and put to output file list1
for /f "skip=2 delims=*" %%a in (%Source%) do (echo %%a >>%list1%)

REM shorten each line to 500 chars and put it to new file
for /f "tokens=* delims=" %%a in ("%list1%") do (
set s=%%a
set s=%s:~0,500% 
echo.%s% >> "%list1_tmp%"
)
REM ^^^^^^^^^^^ this is not working. It puts only 1 space to the output file

rem Parsing the csv file
rem Process the file:
call :ProcessFile < %list1_tmp%
exit /B

:ProcessFile
set /P line=
:nextLine
    set line=:EOF
    set /P line=
    if "!line!" == ":EOF" goto :EOF
    set i=0
    for %%e in (%line%) do (
        set /A i+=1
        for %%i in (!i!) do (
        if %%i==1 echo %%~e >> %expCol%
        if %%i==2 echo %%~e >> %expCol%
    )
    if %%i==3 goto nextLine
    REM I don't want it to process all the columns
    )
goto nextLine

これを見て、2つの列を1つにまとめ、出力を1つのファイルに入れるのを手伝ってもらいたいと思います。

とてもありがたいです。

4

3 に答える 3

2

これはどう?

for /f "skip=2 tokens=2,3 delims=, " %i in (input.csv) do echo %i%j >> output.csv

編集:

/ を改行に置き換えるには、次のようにします。

@echo off

for /f "skip=2 tokens=2,3 delims=, " %%i in (test.csv) do call :replace %%i%%%j
goto :eof

:replace
set string=%*
For /f "tokens=1,* delims=/" %%a in ('echo %string%') Do (
echo.%%a
If not "%%b"=="" call :replace %%b)

次の入力の場合:

title
colA , colB , colC , colD ,...
abc  , def  , g\hi  , jkl  ,...

上記は次のように出力されます。

defg
hi
于 2013-03-20T17:59:47.547 に答える
0

あなたが言及した問題の 1 つは、自然にインタープリターを台無しにするなどの特殊文字が含まれているfor %%e in (%line%) do ...場合、行にあります。%line%(

各列を引用符で囲むために文字列置換を使用することで、これを回避できる場合があります。例(問題のある部分に集中するために、コードの一部をスキップしています):

:ProcessFile
set /P line=
:nextLine
    for %%e in ("%line:,=" "%") do (
        echo %%~e
    )
goto nextLine

この部分に注意してください: "%line:,=" "%". これは、すべてのカンマを に置き換え、行頭と行末に" "追加することです。"

したがって、処理している特定の行が次のようになっているとします。

abc, def (foo), ghi

は次のforように展開されます。

for %%e in ("abc" "def (foo)" "ghi") do ...

(干渉しないように、すべてが引用符で囲まれています。もちろん、特定の列に引用符があると、干渉します...

を使用する次の行は、引用符を削除するため%%eに作成し%%~eます。

于 2013-03-20T18:06:58.690 に答える
0

たまたま今朝、ADODB レコードセットとして CSV ファイルにアクセスして遊んでいました。私のコードはあなたに役立つかもしれません。.csvこのままでは、スクリプトは現在のディレクトリ内のすべてのファイルをループし、column = value各行を表示します。

JScript は、必要に応じて列を結合するように変更するのが非常に簡単なはずです。これはバッチと JScript のハイブリッドであるため、Scripting.FileSystemObjectオブジェクトを作成するか、行の出力をリダイレクトしcscriptて新しい.csvファイルを生成するかを選択できます。

のコードは次のとおりですcsv.bat。*肩をすくめる* これは最終的な答えになることを意図したものではありませんが、試してみるべき代替パスとして提案されています。

@if (@a==@b) @end /*

:: batch portion

@echo off
setlocal

:: force 32-bit environment for ODBC drivers
if exist "%windir%\syswow64\cmd.exe" (set "cmd=%windir%\syswow64\cmd.exe") else set "cmd=cmd.exe"

for /r %%I in (*.csv) do (
    echo Processing %%~nxI:
    echo;
    %cmd% /c cscript /nologo /e:jscript "%~f0" "%%~dpI" "%%~nxI"
    echo;
)

goto :EOF

:: JScript portion */
var conn = new ActiveXObject("ADODB.Connection");
var rs = new ActiveXObject("ADODB.Recordset");

var dsn = "Driver={Microsoft Text Driver (*.txt; *.csv)};"
    + "Dbq=" + WSH.Arguments(0) + ";"
    + "Extensions=asc,csv,tab,txt;";

try { conn.Open(dsn); }
catch(e) {

    // If the Microsoft Text Driver didn't work,
    // try the MS Jet 4.0 provider instead.

    var dsn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
    + WSH.Arguments(0)
    + ";Extended Properties=\"text;HDR=Yes;FMT=Delimited\";";

    try { conn.Open(dsn); }
    catch(e) {

        // If that didn't work either, then give up.

        WSH.Echo("Unable to create ADODB connection.");
        WSH.Quit(1);
    }
}

rs.Open("SELECT * from " + WSH.Arguments(1), conn, 2, 4);

while (!rs.EOF) {
    for (var i=0; i<rs.Fields.Count; i++) {
        WSH.Echo(rs.Fields(i).Name + ' = ' + rs.Fields(i));
    }
    rs.MoveNext;
}

rs.Close();
conn.Close();
于 2013-03-20T18:59:03.207 に答える