Вопрос или проблема
Я новичок в пакетном программировании, и моя жена попросила меня помочь ей ускорить её работу. Вопрос: как мне извлечь дату, номер терминала (00099106), сумму транзакции и комиссию из этого образца текстового файла?
[4w ИСТОРИЯ ДЕЯТЕЛЬНОСТИ POS ТЕРМИНАЛА
ДЛЯ КРЕДИТНОГО НОМЕРА СЧЕТА: 1120162163
Номер отчета: BDO030114 Страница 1
Дата бизнеса: 03/02/2015 Дата формирования: 03/03/2015
=========================================================================================================================================
ТРАНЗАКЦИЯ | ТЕРМИНАЛ | | КАРТА | СЧЕТ | ТРАНЗАКЦИЯ | РЕЗУЛЬТ. | АВТОРИЗ. | РЕВ | СООБЩ. | ТОРГОВЕЦ
ДАТА | ВРЕМЯ | НОМ. | ЧЕК | НОМ. BR | НОМЕР | НОМ. | КОД | СУММА | КОД | МЕТОД | ИНД | ТИП | ДОЛЯ
=========================================================================================================================================
03/01/15 23:54:30 00099106 203 00695 6018530000004863 ************ 00 2,250.00 0 1 210
===================================================================================================
| ТОВАР КАРТЫ | КОЛИЧЕСТВО | СУММА | КОМИССИЯ |
===================================================================================================
00099106 SMARTELLER 1 2,250.00
00099106 ИТОГО: 1 2,250.00
ТОРГОВЕЦ SMARTELLER 1 2,250.00 33.75
ИТОГО ТОРГОВЦА: 1 2,250.00 33.75
ИТОГО ЗА ПОКУПКУ: 1 2,250.00 33.75
ИТОГО ПО ТОРГОВЦУ: 1 2,250.00 33.75
[4w
Вывод должен выглядеть так
03/02/2015;00099106;2,250.00;33.75
Несмотря на то, какой язык программирования или инструмент вы используете, вы должны в первую очередь определить, как вы надежно будете идентифицировать информацию, которую нужно извлечь.
Мне кажется, что ваша дата следует за “Дата бизнеса: ” в начале строки.
Номер терминала следует за “nn/nn/nn nn:nn:nn ” (дата и время) в начале строки.
Вы неясно указываете, какую сумму или комиссию вы хотите. Я предположу, что вы хотите значения, которые следуют за “ИТОГО ПО ТОРГОВЦУ:”
Получить информацию с помощью чистого пакетного скрипта довольно легко.
Для этого примера я предполагаю, что текст находится в файле с именем test.txt.
Команда FINDSTR может искать 3 строки, содержащие ваши данные, используя примитивные регулярные выражения. Опция /R
обрабатывает поиски как регулярные выражения. Я использую отдельную опцию /C:"строка поиска"
, чтобы указать каждую строку поиска, содержащую пробелы. При поиске строки, начинающейся с даты и времени, я решил просто искать слэш и двоеточия с соответствующим количеством символов между ними.
Команда FOR /F анализирует три строки вывода FINDSTR, по одной строке за раз. По умолчанию она обрабатывает пробелы и табуляции как разделители токенов. Строка последовательных пробелов рассматривается как один разделитель. Таким образом, как дата, так и номер терминала являются третьим токеном в строке. Ваша сумма и комиссия являются пятым и шестым токенами в строке.
Поэтому я явно запрашиваю 3-й, 5-й и 6-й токены каждой строки, указывая %%A
как первый захваченный токен. Это означает, что 3-й токен будет в %%A
, 5-й в %%B
, а 6-й в %%C
.
Я явно обнуляю переменные dt
и term
. Строки всегда появляются в одном и том же порядке, поэтому я просто проверяю, определена ли dt
. Если нет, то это первая строка, и я устанавливаю значение даты. В противном случае я проверяю, определена ли term
. Если нет, то это должна быть вторая строка, и я устанавливаю значение терминала. В противном случае это должна быть третья строка, и я устанавливаю значения суммы и комиссии.
@echo off
setlocal
set "dt="
set "term="
for /f "tokens=3,5,6" %%A in (
'findstr /rc:"^Дата бизнеса:" /c:"^../../.. ..:..:.." /c:"ИТОГО ПО ТОРГОВЦУ:" test.txt'
) do (
if not defined dt (
set "dt=%%A"
) else if not defined term (
set "term=%%A"
) else (
set "amt=%%B"
set "comm=%%C"
)
)
echo %dt%;%term%;%amt%;%comm%
Эта задача не была особенно трудной для решения с использованием чистого пакетного скрипта, но часто пакетное программирование не подходит для текстовой обработки. Это часто требует много странного кода и (или) может быть медленным.
Я написал JREPL.BAT – гибридный утилиту JScript/пакет, которая может очень эффективно выполнять сложные операции поиска/замены с регулярными выражениями над текстом. JREPL.BAT – это чистый скрипт, который работает нативно на любой Windows машине начиная с XP. Полная документация встроена в утилиту. Она доступна, если ввести jrepl /?
. Вы можете использовать jrepl /?|more
, если хотите посмотреть помощь по одной странице за раз.
Предположим, что у вас есть JREPL.BAT где-то в вашем PATH, тогда следующее извлечет информацию:
@echo off
call jrepl "[\s\S]*\nДата бизнеса: (.*?) (?:.*\n){5}.*? .*? (.*?) [\s\S]*?ИТОГО ПО ТОРГОВЦУ: +.*? +(.*?) +([^ ]*)[\s\S]*" "$1;$2;$3;$4" /m /f test.txt
echo(
convert.cmd
:
powershell .\convert.ps1
powershell convert.ps1
:
$head=3
$f=gc data.txt
$f[$head..($f.count-1)]|%{
if($_.Contains("Дата бизнеса:" )){$s=$_.split(': ')[3]};
if($_.Contains("ИТОГО ТОРГОВЦА:")){$MT=($_.trim()-replace'\s+',' ').split(' ');$s=$s+';'+$MT[-2]+';'+$MT[-1]};
if($_.Contains("SMARTELLER" )){$SM=($_.trim()-replace'\s+',' ').split(' ');if($SM[0] -ne "ТОРГОВЕЦ"){$s=$s+';'+$SM[0]} };
}
$s|ac short.txt
Вариант 2:
$f=gc data.txt
$s=$f[(3)].Substring(15,10)+';'+$f[(8)].Substring(18,8)+';'
$head=15
$f[$head..($f.count-1)]|%{if($_.Contains("ИТОГО ТОРГОВЦА:")){$MT=($_.trim()-replace'\s+',' ').split(' ');$s=$s+$MT[-2]+';'+$MT[-1]}}
$s|ac short.txt
Вариант 3:
$f=gc data.txt
$s=$f[(3)].Substring(15,10)+';'+$f[(8)].Substring(18,8)+';'+($f[(16)].Substring(80,15)).Trim()+';'+$f[(16)].Substring(102,5)|ac short.txt
Ответ или решение
Ниже приведен полный ответ на вопрос о том, как извлечь конкретные поля из многострочного текстового файла с помощью пакетного файла (.BAT). Я опишу разносторонний подход и предоставлю пример кода.
Решение задачи с помощью пакетного файла (.BAT)
Для извлечения необходимых данных из текстового файла вам потребуется использовать команду FINDSTR
для поиска определенных строк, а затем команду FOR /F
для обработки результата. В данном примере мы будем извлекать дату бизнеса, номер терминала, сумму транзакции и комиссию из файла test.txt
.
Пример кода .BAT
@echo off
setlocal
rem Инициализация переменных
set "dt="
set "term="
set "amt="
set "comm="
rem Обработка файла посредством поиска нужных строк
for /f "tokens=3,5,6" %%A in (
'findstr /rc:"^Business Date:" /c:"^../../.. ..:..:.." /c:"TOTAL PER MERCHANT:" test.txt'
) do (
if not defined dt (
set "dt=%%A"
) else if not defined term (
set "term=%%A"
) else (
set "amt=%%B"
set "comm=%%C"
)
)
rem Форматирование даты
set "dt=%dt:~0,10%"
rem Вывод извлеченных данных
echo %dt%;%term%;%amt%;%comm%
Объяснение кода
-
Инициализация переменных: Мы создаем пустые строки для хранения даты, номера терминала, суммы и комиссии.
-
Поиск строк: Используем команду
FINDSTR
с параметрами:/R
для регулярных выражений./C
для точного поиска строк.
Мы ищем строки, содержащие "Business Date:", текущую дату и "TOTAL PER MERCHANT:".
-
Обработка строк: Команда
FOR /F
позволяет нам циклически обрабатывать каждую найденную строку.tokens=3,5,6
указывает, какие токены мы хотим извлечь. В зависимости от того, какая переменная еще не была определена, мы присваиваем соответствующие значения. -
Форматирование даты: Мы обрезаем дату до нужного формата.
-
Вывод: Наконец, выводим извлеченные данные в нужном формате.
Альтернативный подход
Если вы хотите использовать более мощный инструмент, такой как JREPL.BAT (гибридный JScript/BAT), вы можете обрабатывать текст более эффективно с помощью регулярных выражений.
Пример кода с использованием JREPL.BAT
@echo off
call jrepl "[\s\S]*\nBusiness Date: (.*?) (?:.*\n){5}.*? .*? (.*?) [\s\S]*?TOTAL PER MERCHANT: +.*? +(.*?) +([^ ]*)[\s\S]*" "$1;$2;$3;$4" /m /f test.txt
echo(
Заключение
Выше представлены два подхода к решению вашей задачи: один с использованием стандартного пакетного файла и второй с использованием расширенных возможностей JREPL.BAT для работы с регулярными выражениями. Оба подхода позволят вам извлечь необходимые поля из текстового файла, обеспечив гибкость и контроль над предварительной обработкой данных.