Napisałem skrypt, który zastępuje ogranicznik półkolonowy w pliku tekstowym do przecinków, ale także umieszcza cytaty wokół tekstu 9. kolumny, ponieważ 9. kolumna zawiera przecinki. Po wyjściu do nowego pliku tekstowego przetwarza się bardzo wolno, zajmuje 4-5 minut, plik tekstowy, który czyta jest 50 MB. Czy jest szybszy sposób lub bardziej skuteczny sposób na to? Oto moja do pętli:

FOR /f "usebackq tokens=1-9* delims=;" %%a IN ("%FILENAME%") DO (
SET C10=%%j
ECHO(%%a,%%b,%%c,%%d,%%e,%%f,%%g,%%h,"%%i",!C10:;=,! >> "%MYPATH%\Filename %MMDDYYYY%.csv")

Czy powinienem wystąpić python .....

Dziękuję Ci.

2
arealhobo 17 luty 2017, 05:10

3 odpowiedzi

Najlepsza odpowiedź

Jedną rzeczą, która sprawi, że skrypt Run Szybszy "jest unikanie otwarcia i zamykania pliku wyjściowego dla każdej operacji zapisu

>> "%MYPATH%\Filename %MMDDYYYY%.csv" (
    FOR /f "usebackq tokens=1-9* delims=;" %%a IN ("%FILENAME%") DO (
        SET C10=%%j
        ECHO(%%a,%%b,%%c,%%d,%%e,%%f,%%g,%%h,"%%i",!C10:;=,!
    )
)

Zamiast przekierować każdą linię, przekierować pełne polecenie for.

6
MC ND 17 luty 2017, 06:35

Jeśli chcesz zmienić separatory, aby poprawnie otworzyć CSV w Excelu: nie ma potrzeby tego. Istnieje sztuczka (nieudokumentowana), aby powiedzieć Excel, co char używać jako separator:

(echo Sep=;) > new.csv
type old.csv >> new.csv
move /y new.csv old.csv

Uwaga: Excel czyta Sep=; i importuje resztę pliku za pomocą tego separatora, ale nie jest częścią rozprzestrzeniania, więc jeśli zaoszczędzisz ponownie z programem Excel, {x1}} zostanie utracony (Excel używa { {X2}} lub ; jako separator, w zależności od jego języka instalacji).

4
Stephan 17 luty 2017, 06:45

Squashman miał dobry pomysł, aby użyć mojego Parsecsv.bat Narzędzie wykonać konwersję. Narzędzie to skrypt hybrydowy, który korzysta z obu partii i jscript. Niniejsze narzędzie jest znacznie szybsze niż jakikolwiek roztwór czysty wsadowy, i działa natywnie na dowolnej maszynie Windows od XP do dalszej - nie jest wymagana.

Narzędzie było faktycznie wyprodukowane, aby umożliwić wygodne parsowanie plików CSV za pośrednictwem plików wsadowych. Wersja 1.0 miała jeden problem, który uczynił go mniej niż idealny do używania narzędzia do przekształcenia formatów CSV dla innych zastosowań - Uciekane literały cytatu były niewypowiedziane, aby "" staje się ". Ta transformacja jest przydatna dla parsowania / f, ale nie jest to Ważny format CSV.

Zmodyfikowałem użyteczność, aby mieć możliwość zachowania ucieczki literałów cytatów. Teraz możesz bezpiecznie korzystać z następujących czynności, aby szybko przekonwertować ze średnika do ograniczników przecinających.

parseCSV /I:; /Q:E <input.csv >output.csv

Ponieważ ParseCSV sama jest skryptem wsadowym, musisz użyć call parseCSV, jeśli używasz polecenia w innym skrypcie wsadowym.

Byłem w stanie przekształcić plik 53 MB z parsecsv.bat w 2,5 minuty.

Oto kod dla parsecsv. Nie obiecuję jednak utrzymania tego kodu aktualnego. Polecam, aby uzyskać kod z Dostips Post. Tam również znajdziesz dobry opis innych funkcji narzędzia.

@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScrpt comment

::************ Documentation ***********
::parseCSV.bat version 1.2
:::
:::parseCSV  [/option]...
:::
:::  Parse stdin as CSV and write it to stdout in a way that can be safely
:::  parsed by FOR /F. All columns will be enclosed by quotes so that empty
:::  columns may be preserved. It also supports delimiters, newlines, and
:::  escaped quotes within quoted values. Two consecutive quotes within a
:::  quoted value are converted into one quote by default.
:::
:::  Available options:
:::
:::    /I:string = Input delimiter. Default is a comma (,)
:::
:::    /O:string = Output delimiter. Default is a comma (,)
:::
:::         The entire option must be quoted if specifying poison character
:::         or whitespace literals as a delimiters for /I or /O.
:::
:::         Examples:  pipe = "/I:|"
:::                   space = "/I: "
:::
:::         Standard JScript escape sequences can also be used.
:::
:::         Examples:       tab = /I:\t  or  /I:\x09
:::                   backslash = /I:\\
:::
:::    /E = Encode output delimiter literal within value as \D
:::         Encode newline within value as \N
:::         Encode backslash within value as \S
:::
:::    /D = escape exclamation point and caret for Delayed expansion
:::         ! becomes ^!
:::         ^ becomes ^^
:::
:::    /L = treat all input quotes as quote Literals
:::
:::    /Q:QuoteOutputFormat
:::
:::       Controls output of Quotes, where QuoteOutputFormat may be any
:::       one of the following:
:::
:::         L = all columns quoted, quote Literals output as "   (Default)
:::         E = all columns quoted, quote literals Escaped as ""
:::         N = No columns quoted, quote literals output as "
:::
:::       The /Q:E and /Q:N options are useful for transforming data for
:::       purposes other than parsing by FOR /F
:::
:::    /U = Write unix style lines with newline (\n) instead of the default
:::         Windows style of carriage return and linefeed (\r\n).
:::
:::parseCSV  /?
:::
:::  Display this help
:::
:::parseCSV  /V
:::
:::  Display the version of parseCSV.bat
:::
:::parseCSV.bat was written by Dave Benham. Updates are available at the original
:::posting site: http://www.dostips.com/forum/viewtopic.php?f=3&t=5702
:::

::************ Batch portion ***********
@echo off
if "%~1" equ "/?" (
  setlocal disableDelayedExpansion
  for /f "delims=: tokens=*" %%A in ('findstr "^:::" "%~f0"') do echo(%%A
  exit /b 0
)
if /i "%~1" equ "/V" (
  for /f "delims=:" %%A in ('findstr /bc:"::%~nx0 version " "%~f0"') do echo %%A
  exit /b 0
)
cscript //E:JScript //nologo "%~f0" %*
exit /b 0


************ JScript portion ***********/
var args     = WScript.Arguments.Named,
    stdin    = WScript.Stdin,
    stdout   = WScript.Stdout,
    escape   = args.Exists("E"),
    literalQ = args.Exists("L"),
    escapeQ  = (args.Item("Q")&&args.Item("Q").toUpperCase()=="E"),
    quoteCol = (args.Item("Q")&&args.Item("Q").toUpperCase()=="N") ? '' : '"',
    delayed  = args.Exists("D"),
    inDelim  = args.Item("I") ? eval('"'+args.Item("I")+'"') : ",",
    outDelim = args.Item("O") ? eval('"'+args.Item("O")+'"') : ",",
    newline  = args.Exists("U") ? "\n" : "\r\n",
    quote    = false,
    ln, c, n, out;
while (!stdin.AtEndOfStream) {
  ln=stdin.ReadLine();
  out="";
  if (!quote) stdout.Write(quoteCol);
  for (n=0; n<ln.length; n++ ) {
    c=ln.charAt(n);
    if (c == '"') {
      if (literalQ) {
        if (escapeQ) c+='"';
      } else if (quote && ln.charAt(n+1) == '"') {
        n++;
        if (escapeQ) c+='"';
      } else {
        quote=!quote;
        continue;
      }
    }
    else if (c == inDelim && !quote) c=quoteCol+outDelim+quoteCol;
    else if (escape) {
      if (c == outDelim) c="\\D";
      if (c == "\\") c="\\S";
    }
    else if (delayed) {
      if (c == "!") c="^!";
      if (c == "^") c="^^";
    }
    out+=c;
  }
  out += (quote) ? ((escape) ? "\\N" : newline) : quoteCol+newline;
  stdout.Write(out);
}
1
dbenham 20 luty 2017, 04:57