Как удалить все, кроме последней ячейки в CSV, используя CMD

моя цель - написать сценарий, который будет отслеживать использование памяти процессом и запускать сравнение на основе %, чтобы определить, есть ли утечка памяти в указанном процессе.

Я использую следующую команду, чтобы получить момори использование процесса:

список задач /fi "imagename eq %PROCESS%" /FO csv | найтистр K

ПРИМЕР: "cmd.exe", "11640", "Консоль", "1", "3160 КБ"

Это дает мне файл CSV, в котором последняя ячейка представляет собой использование памяти. У меня есть две проблемы, с которыми мне нужна помощь.

Проблема 1) Как удалить все ячейки, кроме последней, чтобы затем присвоить килобайты, используемые переменной для сравнения.

Проблема 2) Как избавиться от запятой в числе? Это затрудняет использование запятой в качестве разделителя:/

Есть ли лучшая команда, чем список задач для этого? Мне просто нужно исходное число, которое использует программа, оно может быть в КБ или МБ.

Мне бы хотелось иметь возможность не иметь зависимостей, но если мне нужны зависимости, я могу включить их в пакет.

Также есть ли способ, чтобы findstr не возвращал всю строку?

Спасибо за любую помощь! Я пытался решить эту проблему уже два дня, но без особого успеха.


person Duxa    schedule 16.07.2013    source источник


Ответы (1)


@ECHO OFF
SETLOCAL
FOR /f "delims=" %%i IN (memcsv.csv) DO CALL :process %%i 

GOTO :EOF
:process
SET memsize=%~5
SET memsize=%memsize:,=%
ECHO memsize found = %memsize%
GOTO :eof

Это должно привести ваш вывод в переменную с именем memsize.

В качестве входных данных используется файл memcsv.csv, но вы можете заменить mmcsv.csv на

'tasklist /fi "imagename eq %PROCESS%" /FO csv ^| findstr Mem'

работать непосредственно на выходе FINDSTR. Таким образом, ваша результирующая строка будет

FOR /f "delims=" %%i IN ('tasklist /fi "imagename eq %PROCESS%" /FO csv ^| findstr Mem') DO CALL :process %%i 

который для простоты чтения можно было бы ввести как

FOR /f "delims=" %%i IN (
  'tasklist /fi "imagename eq %PROCESS%" /FO csv ^| findstr Mem'
  ) DO CALL :process %%i 

Обратите внимание, что разрывы строк специфичны - до и после одинарной кавычки.

Также, что одинарные кавычки ТРЕБУЮТСЯ и что перед каналом (|) стоит знак вставки (^), который сообщает cmd, что канал является частью команды, которая должна быть выполнена, а не частью команды FOR.


Изменить, чтобы добавить объяснение КАК.

Выходные данные tasklist...|findstr... можно использовать как входные данные для for/f, как если бы это был файл. Все, что вам нужно сделать, это окружить команду SINGLE-QUOTES и убедиться, что перенаправители, такие как | < >, "экранированы" символом вставки.

FOR /F «читает» «файл» построчно, присваивая (по умолчанию) первый «токен» в строке «метапеременной» (переменная управления циклом, %%i в приведенном выше случае). Это поведение можно изменить, добавив управляющие предложения в FOR/F. Вы можете использовать `tokens=x,y,z", например, чтобы присвоить номер токена x, номер y и номер z %%i, %%j, %%k соответственно.

TOKENS отсчитываются от 1 и имеют значение содержимого строки до (серии) разделителей. По умолчанию в качестве разделителей используются пробелы, запятые, точки с запятой и символы табуляции, поэтому строка

TOKEN_ONE TOKEN_2,TOKEN_THREE;Token_FOUR

когда увидит

for /f "tokens=1,3,4" %%i in (filecontainingaboveline) do

установит %%i=TOKEN_ONE %%j=TOKEN_THREE %%k=Token_FOUR

Использование "delims=" отключает разделители, и, следовательно, ВСЯ строка назначается метапеременной.

ОТНОСИТЕЛЬНО, в приведенном выше коде вся строка назначается %%i и доставляется подпрограмме :process.

С точки зрения :process ему был присвоен аргумент ** "cmd.exe", "11640", "Console", "1", "3,160 K"**, который он интерпретирует как последовательность из 5 параметров, разделенных запятыми - и запятая (или любой другой разделитель) ВНУТРИ "кавычек" - это данные, а не разделитель.

Доступ к параметру номер 5 осуществляется с помощью %5, то есть "3,160 K", включая кавычки и запятую.

В переменную устанавливается значение пятого параметра — тильда (~) означает «удалить заключающие кавычки». Следовательно, memsize получает значение 3,160 K Следующее SET заменяет строку после двоеточия в назначенной переменной на строку после = - запятые ничего не заменяют, а результат присваивает переменной memsize.

goto :eof означает "перейти к физическому концу файла". Это очень специфично - ДОЛЖНО присутствовать двоеточие. Достижение конца файла завершает подпрограмму или пакетный процесс.

Чтобы удалить последние 2 символа переменной, вы можете использовать

SET var=%var:0,~-2%

где var — имя переменной.

ВИДЕТЬ

SET /?

из подсказки для документации.

Также GOTO /? и FOR/? для более подробной информации об этих командах...

person Magoo    schedule 16.07.2013
comment
Что такое :EOF? кажется, что скрипт никуда не денется, когда эта строка будет достигнута? - person Duxa; 16.07.2013
comment
Я изменил материал EOF на следующий код, и теперь он, кажется, работает хорошо :) Как мне также избавиться от K в конце целого числа memsize? И какие-нибудь пробелы вокруг, так что это просто необработанное число? SETLOCAL FOR /f "delims=" %%i IN ('tasklist /fi "imagename eq cmd.exe" /FO csv ^| findstr K') DO CALL :process %%i GOTO processend :process SET memsize=%~5 SET memsize=%memsize:,=% ECHO memsize found = %memsize% :processend Спасибо! - person Duxa; 16.07.2013
comment
Спасибо за объяснение, Питер, я пытаюсь использовать SET var=%var:~-2%, но это просто отображает два последних символа: K пробел и K. Я ничего не могу найти об усечении элементов в SET /? - person Duxa; 16.07.2013
comment
Гм - должно быть :~0,-2 - теперь исправлено. Конечно есть документация - на второй странице. Я использую переменную PATH, но она будет работать с любой переменной. Комбинация :~0,-2 означает от первого символа (т.е. символа 0) до (последнего -2) - person Magoo; 16.07.2013
comment
Большое спасибо за помощь, Петр :) - person Duxa; 16.07.2013
comment
Хм, столкнулся с проблемой, похоже, CMD не хватает выделенной памяти (которая, я думаю, составляет 4 мегабайта) и происходит сбой? Занимает около минуты или двух бега. Мне нужно, чтобы эта штука работала как минимум 4 дня. Я предполагаю, что это потому, что эта команда занимает так много. Мне не нужно, чтобы он проходил через все экземпляры процесса, как его упростить? Может быть, не включать его в цикл FOR? - person Duxa; 17.07.2013
comment
Похоже, в этом цикле for есть какая-то утечка памяти, которую удалось обойти, поместив ее во временный файл bat, который вызывается для получения переменной. если у вас есть другие идеи, пожалуйста, дайте мне знать :) - person Duxa; 17.07.2013
comment
Не вижу, что эти несколько инструкций приведут к описанной вами проблеме. Вам нужно поставить проблему в контекст. Этот код будет выполняться только один раз — что заставляет его выполняться как минимум 4 дня? И TASKLIST не медленный - нужно увидеть гораздо больше того, что вы делаете, чтобы проанализировать проблему - и лучше в качестве нового вопроса (они не так строго нормированы, не так ли?), так как это исчерпание- проблема с памятью имеет мало общего с предметом этого вопроса. - person Magoo; 18.07.2013