Есть ли способ изменить вывод командной строки перед сохранением в файл?

Я пишу программу, которая использует команду «tracert» для поиска маршрутов трассировки для IP-адресов, которые я затем буду использовать для некоторых действий.

Как я планировал это сделать, так это сбросить вывод для всех IP-адресов в текстовый файл, добавив >>output.txt, а затем прочитать его с помощью Python или чего-то еще и превратить его во что-то полезное.

Моя проблема заключается в том, что tracert также показывает в своем выводе некоторые вещи, которые мне бесполезны, например, первая строка, в которой говорится, куда идет трассировка и каково максимальное количество переходов, или последняя строка, в которой говорится только: «Трассировка завершена».

Дело в том, что я собираюсь отслеживать более 3500 IP-адресов, и это число будет только расти, так что это куча текста, который я печатаю в файле, который абсолютно бесполезен.

Вот почему мой вопрос: есть ли способ изменить вывод команды перед ее сохранением в пакетном файле?

Команда, которую я запускаю:

tracert -h 30 -w 500 XX.XXX.XXX.XX >>cmd_output.txt

Результат, который он дает:

Tracing route to XYZ.net 
[XX.XXX.XXX.XX]
over a maximum of 30 hops:

  1    41 ms    18 ms     2 ms  text.net [XXX.XXX.XXX.X] 
  2     2 ms     1 ms     1 ms  text.net [XX.XXX.XXX.XXX] 
  3     1 ms     1 ms     1 ms  text.net [XX.XXX.XXX.XXX] 
  4     5 ms     5 ms     5 ms  text.net [XXX.XX.XX.XXX] 
  5     5 ms     5 ms     5 ms  text.net [XXX.XX.XX.X] 
  6    25 ms    25 ms    25 ms  XYZ.net [XX.XXX.XXX.XX] 

Trace complete.

person Sander Franken    schedule 01.09.2017    source источник
comment
самый простой способ: tracert www.google.com|find " ms ">>file.txt или tracert www.google.com||findstr /bc:" " (печатать только строки, начинающиеся с пробела)   -  person Stephan    schedule 01.09.2017
comment
Вы сказали нам то, что считаете бесполезным, но не то, что вы на самом деле хотите в своем выводе. На мой взгляд, я тоже не вижу смысла во всех столбцах. Пожалуйста, дайте нам знать, что вы хотите, пока исследуете, как сделать это самостоятельно, потому что это не сайт запросов на кодирование.   -  person Compo    schedule 01.09.2017
comment
Возникает вопрос: Можно ли каким-либо образом изменить вывод CMD перед его сохранением в пакетном файле? И ответ: Да, существует несколько способов фильтрации или переформатирования. вывод приложения перед записью в файл. Нам не нужно было писать больше, но Стефан уже предложил использовать из FINDSTR. FIND можно также использовать в качестве приложения-фильтра. Также можно использовать FOR, SET и IF для переформатирования вывода перед записью в файл. И еще много способов. Запустите их с /? для помощи.   -  person Mofi    schedule 01.09.2017
comment
Вы должны принять ответ от @Stephan. Это то, что ты хочешь.   -  person JJF    schedule 01.09.2017
comment
@JJF: трудно принять комментарий ... Этот вопрос слишком широк, чтобы на него можно было ответить. Как уже отмечал Compo, нам нужно знать, по крайней мере, какой выход требуется.   -  person Stephan    schedule 01.09.2017
comment
Спасибо, ребята, я стараюсь быть максимально ясным, но я впервые задаю вопрос здесь, спасибо за вашу доброту. Мне действительно нужен только номер прыжка и связанный с ним IP-адрес. Я проведу небольшое исследование метода findstr. Возможно, вы могли бы указать мне направление, где я мог бы найти документацию для такого программирования? Я, вероятно, не искал нужные вещи, чтобы получить документацию.   -  person Sander Franken    schedule 03.09.2017
comment
Как следует обрабатывать что-то вроде 4 * * * Request timed out.?   -  person Stephan    schedule 03.09.2017


Ответы (4)


Возможно, поможет следующее, я считаю, что вы можете использовать его и настроить для собственного использования: Пакетная обработка — анализ вывода Tracert

person jorgesimoes    schedule 03.09.2017

Точная формула для пропуска N первых строк из вывода одной команды:

for /f "skip=N tokens=*" %a in ('<command>') do @echo %a

В твоем случае:

for /f "skip=4 tokens=*" %a in ('tracert -h 30 -w 500 XX.XXX.XXX.XX ') do @echo %a >> cmd_output.txt
person Little Santi    schedule 03.09.2017

Используя ваши ответы и еще несколько поисков, я придумал это решение:

@echo off
rem token 1 is hop-number
rem token 6,7 or 8 may be IP, depending on whether 2 or less requests dont receive a response.
for /f "tokens=1,6,7,8 delims=* " %%a in ('tracert -d -h 30 -w 350 8.8.8.8^|findstr /bc:" " ') do (
  echo %%a, %%b, %%c, %%d
  )>>ips.txt
endlocal

Это дает следующий ответ:

1, <1, ms, 192.168.1.240
2, 1, ms, 195.114.237.65
3, 1, ms, 94.247.72.33
4, <1, ms, 82.150.154.129
5, 1, ms, 217.170.0.244
6, 2, ms, 193.239.117.142
7, 2, ms, 108.170.241.140
8, 2, ms, 216.239.41.49
9, 5, ms, 74.125.37.130
10, 209.85.243.253, , 
11, 5, ms, 108.170.237.135
12, , , 
13, 5, ms, 8.8.8.8

В каждой строке перед первой запятой всегда указывается номер перехода. Тогда IP-адрес может быть после первой, второй или третьей запятой. Поскольку tracert отправляет три запроса на переход, один, два или три из этих запросов могут завершиться ошибкой.

Если запрос завершается неудачно, результатом будет «*» вместо «X мс», и, поскольку я разделяю пробелами, если бы я всегда брал 8-й токен, он мог бы не содержать IP-адрес или что-либо в этом отношении.

Этот код всегда будет содержать IP-адрес, но по-прежнему будет содержать некоторые лишние данные, если число неудачных запросов меньше двух, потому что тогда токен 6 или 7 будет содержать некоторую часть «X мс».

В ответе вы увидите, что все запросы были успешными, за исключением прыжка 10, где два запроса завершились неудачно, и прыжка 12, где три запроса завершились неудачно, и поэтому tracert не смог вернуть IP-адрес.

Если у кого-нибудь есть какие-нибудь яркие идеи о том, как удалить эти последние биты лишних данных, мы будем признательны. В противном случае это вполне рабочий выход для меня. Так что спасибо за вашу помощь! :)

person Sander Franken    schedule 04.09.2017

@echo off
setlocal enabledelayedexpansion
for /f "tokens=1,*" %%a in ('tracert -d -h 30 -w 350 8.8.8.8 ^|findstr /bc:" "') do (
  for %%c in (%%b) do set ip=%%c
  set ip=!ip:[=!
  set ip=!ip:]=!
  echo !ip!|findstr "[0-9]" >nul || set "ip=-"
  echo %%a, !ip!
)

второй for (%%c) получает самое последнее слово строки (которое является либо IP-адресом, либо IP-адресом в скобках, либо последним словом «Время ожидания запроса истекло» (out. в англоязычных версиях Windows). Остальная часть строк просто для украшения результата (удаление скобок, замена всего, что не имеет номера (не IP-адреса) на -

Возможно, вы захотите заменить две строки echo ... только на:

  echo !ip!|findstr "[0-9]" >nul && echo %%a, !ip!

Это не будет выводить строки без IP-адреса.

Подробнее о && и || см. SS64.

Для синтаксиса !variable! см. отложенное расширение

person Stephan    schedule 04.09.2017