Как получить требуемый вывод из файла bat в файл csv?

Мне пришлось написать файл .Bat в командной строке MS-Command, чтобы извлечь 2 конкретные строки «Имя пользователя» и «время последнего входа» из папки, имеющей, скажем, 100 файлов журнала, и каждый из этих файлов журнала имеет эти 2 вещи. Вывод должен быть распечатан в отчет в формате csv для сохранения где-либо.

echo Processing user's last login time. Please wait...
S:
cd log_files

for %G IN (*.txt) do (findstr /i "Username: Log-In" "%G" >> S:\Sourav\GIS_Login_Time.txt)
echo Execution Complete.
echo Output file created in C:\data folder.
pause

Выходной файл (в формате txt) выглядит следующим образом:

*** OS Username:              ADIELA
*** GIS Username:             adiela ( Laura Adie - Horizons, Bullion )
*** Log-In Time:              21/07/2014 06:37:20
*** OS Username:              allanj1
*** GIS Username:             allanj ( Jim Allan - Shared access Lomond House )
*** Log-In Time:              17/12/2014 11:44:22
...

Не могли бы вы посоветовать, как изменить вывод (который теперь идет в текстовый файл), чтобы перейти в файл csv? Выходной файл должен иметь 3 столбца. 1) Имя пользователя ОС 2) Имя пользователя ГИС 3) Время входа в систему. Я был бы очень признателен, если бы я мог получить некоторые ценные предложения для этого. Заранее спасибо :)


person Sourav Sircar    schedule 24.12.2014    source источник
comment
Зачем бороться со сценарием оболочки (пакетным), если можно использовать PowerShell?   -  person Bill_Stewart    schedule 24.12.2014


Ответы (3)


Еще одна идеальная задача для моей утилиты JREPL.BAT — гибридный JScript /batch скрипт, выполняющий поиск и замену текста по регулярному выражению. JREPL.BAT — это чистый скрипт, который изначально запускается на любом компьютере с Windows, начиная с XP.

Предполагая, что в каждом файле есть все три записи в одном и том же порядке (хотя и не обязательно последовательно), тогда этот один вкладыш создаст «output.csv». Обратите внимание, что я использовал продолжение строки только для того, чтобы код было легче читать.

type *.txt 2>&1 | jrepl ^
  "OS Username:\s*(.*?)$[\s\S]*?GIS Username:\s*(.*?)$[\s\S]*?Log-In Time:\s*(.*?)$" ^
  "'\x22'+$1+'\x22,\x22'+$2+'\x22,\x22'+$3+'\x22'" ^
  /m /jmatch /o output.csv

-- ВЫВОД, используя текст примера --

"ADIELA","adiela ( Laura Adie - Horizons, Bullion )","21/07/2014 06:37:20"
"allanj1","allanj ( Jim Allan - Shared access Lomond House )","17/12/2014 11:44:22"


Если вам действительно нужно только имя пользователя GPS без информации в скобках, вам не нужны кавычки, потому что ваши данные больше не содержат запятых:

type *.txt 2>&1 | jrepl ^
  "OS Username:\s*(.*?)$[\s\S]*?GIS Username:\s*(.*?)\s[\s\S]*?Log-In Time:\s*(.*?)$" ^
  "$1+','+$2+','+$3" ^
  /m /jmatch /o output.csv

-- ВЫХОД --

ADIELA,adiela,21/07/2014 06:37:20
allanj1,allanj,17/12/2014 11:44:22


Легко добавить строку заголовка, в которой перечислены имена столбцов:

type *.txt 2>&1 | jrepl ^
  "OS Username:\s*(.*?)$[\s\S]*?GIS Username:\s*(.*?)\s[\s\S]*?Log-In Time:\s*(.*?)$" ^
  "$1+','+$2+','+$3" ^
  /jbeg "output.WriteLine('OS Username,GIS Username,Login Time')" ^
  /m /jmatch /o output.csv

-- ВЫХОД --

OS Username,GIS Username,Login Time
ADIELA,adiela,21/07/2014 06:37:20
allanj1,allanj,17/12/2014 11:44:22
person dbenham    schedule 24.12.2014

Это было хорошо. Вот как я это решил:

@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion

SET SourceFile="C:\SourceFile.txt"
SET OutputFile="C:\List.txt"

SET TempFile1="%TEMP%\1.txt"
SET TempFile2="%TEMP%\2.txt"
SET TempFile3="%TEMP%\3.txt"

REM Initialize files.
ECHO Header>%TempFile1%
ECHO Header>%TempFile2%
ECHO Header>%TempFile3%

IF EXIST %OutputFile% DEL %OutputFile%

REM Build a list of each value.
FOR /F "usebackq tokens=1,* delims=:" %%A IN (`FINDSTR /L "OS" %SourceFile%`) DO ECHO %%B>>%TempFile1%
FOR /F "usebackq tokens=1,* delims=:" %%A IN (`FINDSTR /L "GIS" %SourceFile%`) DO ECHO %%B>>%TempFile2%
FOR /F "usebackq tokens=1,* delims=:" %%A IN (`FINDSTR /L "Log-In" %SourceFile%`) DO ECHO %%B>>%TempFile3%

REM All temp files should have the same number of entries.
REM Concatenate them with a comma.
SET Skip=1

:ProcessLine
REM Keep going until we find the first empty entry.
REM This means we reached the end of the list.
SET "OSUserName="
SET "GISUserName="
SET "LogInTime="

REM Only set the first line.
FOR /F "usebackq tokens=* skip=%Skip% delims= " %%A IN (%TempFile1%) DO IF "!OSUserName!"=="" SET OSUserName=%%A
FOR /F "usebackq tokens=* skip=%Skip% delims= " %%A IN (%TempFile2%) DO IF "!GISUserName!"=="" SET GISUserName=%%A
FOR /F "usebackq tokens=* skip=%Skip% delims= " %%A IN (%TempFile3%) DO IF "!LogInTime!"=="" SET LogInTime=%%A

ECHO %OSUserName%
REM Check for the end of the list.
IF "%OSUserName%"=="" GOTO Finish

REM Add to the output.
ECHO %OSUserName%,%GISUserName%,%LogInTime%>>%OutputFile%

REM Increment counter and loop.
SET /A Skip=%Skip%+1
GOTO ProcessLine

:Finish
REM Cleanup.
IF EXIST %TempFile1% DEL %TempFile1%
IF EXIST %TempFile2% DEL %TempFile2%
IF EXIST %TempFile3% DEL %TempFile3%

ENDLOCAL
person Jason Faulkner    schedule 24.12.2014

Это создает ваш csv непосредственно из исходных файлов (без временного файла):

@echo off
setlocal enabledelayedexpansion
REM write first line:
echo OSUser;GISUser;LoginTime >out.csv
REM for every .txt file:
for %%i in (*.txt) do (
  REM add the three strings: 
  set "x="
  for /f "tokens=1,* delims=:" %%a in ('findstr "Username Log-In" %%i') do set x=!x!%%b;
  REM delete any "two consecutive spaces":
  set x=!x:  =!
  REM delete TABs ( it's a TAB between : and = ):
  set x=!x:       =!
  REM delete last ; (if it disturbes you):
  set x=!x:~0,-1!
  REM write it to the file:
  echo !x!>>out.csv
)
person Stephan    schedule 24.12.2014