2014-08-27 2 views
3

У меня есть файл (file1.csv), который имеет два значения, разделенные запятыми. Мне нужен способ удалить начальный нуль из обоих значений в одном пакетном файле.Как удалить ведущие нули из файла с разделителями-запятыми

До сих пор я использовал это:

@echo off 
(for /f "tokens=*,* delims=0" %%a in (file1.csv) do echo(%%a)>stripped.txt 

Она работает довольно хорошо, хотя он удаляет только нули с первого числа, а не второй.

Пример из file1.csv:

00,00000

00067890,00000067890 

Пример из после использования выше пакетного файла:

12345,00000

67890,00000067890 

Кто-нибудь есть предложения о том, как я могу сделать то же самое для числа после запятой?

+0

Ваш код для меня совсем не работает. Я получаю ', * delims = 0" было неожиданным в это время. 'Когда я запускаю его. – aphoria

ответ

5

Если вы готовы использовать гибридную JScript/пакетную утилиту REPL.BAT, то решение может быть столь же просто, как:

type file.csv|repl "0*(\d\d*),0*(\d\d*)" "$1,$2" >stripped.csv 

Это не только REPL.BAT решение простое, оно также очень эффективно. Он может обрабатывать большой CSV довольно быстро.

Если у вас должно быть чистое пакетное решение, то здесь используется тот, который не использует CALL или GOTO или замедленное расширение, и он правильно обрабатывает значение 0. Это будет значительно медленнее, чем решение REPL.BAT, но Я думаю, что это наиболее эффективное решение для чистого пакета.

Первый цикл анализирует линию на два значения.

Затем для каждого значения есть еще две петли. Первая строка содержит начальные нули, но также добавляет дополнительное значение 0 после пробела, так что оно всегда возвращает строку, даже если значение равно 0. Последний цикл затем возвращает либо исходное нулевое значение, либо если оно было исключено, потому что оно равно 0, тогда оно возвращает добавленное значение 0.

@echo off 
(for /f "delims=, tokens=1,2" %%A in (file.csv) do (
    for /f "delims=0 tokens=*" %%C in ("%%A 0") do for /f %%E in ("%%C") do (
    for /f "delims=0 tokens=*" %%D in ("%%B 0") do for /f %%F in ("%%D") do (
     echo %%E,%%F 
    ) 
) 
))>stripped.csv 

Код для разметки ведущих нулей может быть инкапсулирован в функцию, а затем он станет более удобным в использовании. Это особенно верно, если у вас есть много значений в строке для разметки. Но механизм CALL довольно медленный. Для этой простой задачи с двумя значениями раздеться, это замедляет решение вниз более чем в два раза 5.

@echo off 
setlocal enableDelayedExpansion 

(for /f "delims=, tokens=1,2" %%A in (file.csv) do (
    call Strip0 %%A A 
    call Strip0 %%B B 
    echo !A!,!B! 
))>stripped.csv 
exit /b 

:strip0 ValueStr [RtnVar] 
:: 
:: Strip leading zeros from value ValueStr and store the result in vaiable RtnVar. 
:: If RtnVar is not specified, then print the result to stdout. 
:: 
for /f "delims=0 tokens=*" %%A in ("%~1") do for /f %%B in ("%%A 0") do (
    if "%~2" equ "" (echo %%B) else set "%~2=%%B" 
) 
exit /b 

Существует продвинутая партия макро метод, который может инкапсулировать логику в макро-функции без значительного замедления вещей вниз. См. http://www.dostips.com/forum/viewtopic.php?f=3&t=1827 для получения справочной информации о пакетных макросах с аргументами.

Это решение, использующее макрос партии. Это в 4 раза быстрее, чем метод CALL.

@echo off 

:: The code to define the macro requires that delayed expansion is disabled. 
setlocal disableDelayedExpansion 
call :defineStrip0 

:: This example requires delayed expansion within the loop 
setlocal enableDelayedExpansion 
(for /f "delims=, tokens=1,2" %%A in (file.csv) do (
    %strip0% %%A A 
    %strip0% %%B B 
    echo !A!,!B! 
))>stripped.csv 
exit /b 


:defineStrip0 The code below defines the macro. 

:: Define LF to contain a linefeed character (0x0A) 
set ^"LF=^ 

^" The above empty line is critical - DO NOT REMOVE 

:: Define a newline with line continuation 
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^" 

::%strip0% ValueStr [RtnVar] 
:: 
:: Strip leading zeros from string ValueStr and return the result in variable StrVar. 
:: If RtnVar is not specified, then print the result to stdout. 
:: 
set strip0=%\n% 
for %%# in (1 2) do if %%#==2 (setlocal enableDelayedExpansion^&for /f "tokens=1,2" %%1 in ("!args!") do (%\n% 
    for /f "delims=0 tokens=*" %%A in ("%%1") do for /f %%B in ("%%A 0") do (%\n% 
    endlocal^&if "%%2" equ "" (echo %%B) else set "%%2=%%B"%\n% 
)%\n% 
)) else set args= 
exit /b 
+0

+1 Умный. Я не видел проблему со всеми нулевыми значениями. Спасибо. –

1

EDIT: Мой первый код был не прав! Эта версия работает нормально:

@echo off 
setlocal EnableDelayedExpansion 

(for /f "tokens=1,2 delims=," %%a in (file1.csv) do (
    call :leftZero %%a first= 
    call :leftZero %%b second= 
    echo !first!,!second! 
))>stripped.txt 
goto :EOF 

:leftZero 
set num=%1 
:nextZero 
    if "%num:~0,1%" neq "0" goto endLeftZero 
    set num=%num:~1% 
goto nextZero 
:endLeftZero 
set %2=%num% 
exit /B 
+0

Я тоже начал этот путь, но он переносит конечные нули с чисел во второй строке. – aphoria

+0

Ничего себе! Спасибо! – Mike