Пакет - Удалить диапазон / определенные слова

По желанию я распечатываю список отложенных / изменений в файле с помощью следующего пакетного сценария:

for %%A IN (%ShelvedCHL%) DO (
    echo Change List: %%A 
    p4 -p %PPort% -c %PClient% unshelve -s %%A && if NOT %ERRORLEVEL%==0 exit -1
)>> list.txt

Вот мой list.txt

Список изменений: 24536

//GSA/TOC.h#1 - unshelved, opened for edit
... /GSA/TOC.h - also opened by test@dev
... /GSA/TOC.h - also opened by test@dev
//odata/oenums.h#6 - unshelved, opened for edit
... //odata/oenums.h#6 - also opened by test@dev

Я хочу получить следующий вывод, в основном удалить предложение после - также с тире: или даже любую команду perforce, чтобы иметь меньше информации и просто список файлов:

 //GSA/TOC.h#1 
 ... /GSA/TOC.h
 ... /GSA/TOC.h
 //odata/oenums.h#6
 ... //odata/oenums.h#6

Буду признателен за любую помощь, заранее спасибо!


176
2

Ответы:

Сначала давайте взглянем на ваш код:

  1. Я не знаю программу p4, но предполагаю, что она устанавливает ErrorLevel. Так как это значение обновляется в том же блоке кода, в котором вы хотите его прочитать, вам нужно использовать отложенное расширение, поэтому поместите setlocal EnableDelayedExpansion поверх вашего скрипта и используйте !ErrorLevel! вместо %ErrorLevel%. Другой способ - заменить if not !ErrorLevel!==0 на ifnot ErrorLevel 1, означающий если ErrorLevel не больше и не равно 1, или выраженный более простым способом, если ErrorLevel меньше 1, но это работает, только если программа не устанавливает отрицательное значение.
  2. Даже если вы исправили проблему ErrorLevel, запрос if никогда не будет выполнен из-за оператор конкатенации условных команд %%, потому что это позволяет следующей команде выполняться только в случае успеха предыдущей, что означает, что ее код выхода 1 равен нулю. Поэтому для выполнения оператора if используйте безусловный оператор &. В любом случае, есть еще один условный оператор ||, который позволяет следующей команде выполняться только в том случае, если код выхода имеет ненулевое значение; это может полностью заменить ваше состояние if.
  3. Команда exit не только закрывает пакетный файл, но и завершает работу экземпляра командной строки (cmd), в котором выполнялся пакетный сценарий. Для выхода из пакетного файла используйте вместо этого только exit /B.
  4. Вы устанавливаете ErrorLevel на -1 через exit -1. Вы, конечно, можете это сделать, но обычно отрицательных значений избегают; поэтому позвольте мне предложить положительное значение, например 1 (от exit /B 1).
  5. Вы открываете и закрываете файл list.txt для каждой итерации for петля. Это снижает общую производительность. Кроме того, если list.txt уже существует, данные добавляются; если вы этого не хотите, вам нужно поместить del "list.txt" 2> nul перед циклом for для первоначального удаления файла. В любом случае, чтобы записать сразу весь файл, заключите еще одну пару скобок в цикл for. Затем вы можете выбрать, следует ли добавить к уже существующему файлу с помощью оператор перенаправления >> или перезаписать его с помощью оператора > (без необходимости сначала удалять его).

Все это приводит к следующему улучшенному сценарию:

(for %%A in (%ShelvedCHL%) do (
    echo Change List: %%A 
    p4 -p %PPort% -c %PClient% unshelve -s %%A || exit /B 1
)) > "list.txt"

В зависимости от того, что содержит %ShelvedCHL% (кажется, это 24536 в ваших данных образца, а не путь / имя / маска файла), цикл for может быть даже лишним, хотя я не могу знать на данный момент ...


В любом случае, все вышеперечисленное еще не учитывает удаление частичной строки, начинающейся с SPACE + - + SPACE, поэтому давайте реализуем это сейчас:

Чтобы не усложнять, мы могли бы просто изменить файл list.txt после приведенного выше кода, используя этот код (см. Все пояснительные примечания к rem; упомянутая манипуляция со строкой называется подстановка подстроки):

rem // Read file `list.txt` line by line:
(for /F "usebackq delims= eol=|" %%L in ("list.txt") do (
    rem // Assign line string to variable:
    set "LINE=%%L"
    rem // Enable delayed expansion to be able to do string manipulation:
    setlocal EnableDelayedExpansion
    rem /* Replace every occurrence of ` - ` by a single character `|`, then use this one
    rem    as a delimiter to split the line string as `for /F` requires single-character
    rem    delimiters; just using `-` is not good as they might occur in the partial
    rem    strings that need to be kept, I suppose; the `|` must not occur in them: */
    for /F "tokens=1 delims=| eol=|" %%K in ("!LINE: - =|!") do (
        rem // Disable delayed expansion to not lose `!`-marks:
        endlocal
        rem // Return the split string, that is the part before the (first) ` - `:
        echo %%K
    )
)) > "list_NEW.txt"

Полученные данные содержатся в файле list_NEW.txt. Чтобы сохранить его в исходном файле, добавьте в код следующую строку:

move /Y "list_NEW.txt" "list.txt" > nul

1... Usually the exit code and ErrorLevel are the same, but there are in fact some rare cases where they may differ.


Вы можете сделать это в p4 изначально, практически не выполняя никаких сценариев. Посмотрите это сообщение в блоге:

https://www.perforce.com/blog/fun-formatting

Вы можете увидеть поля в сообщении Perforce, запустив его с глобальной опцией -e *, например:

p4 -e files ...

Затем вы можете использовать любое или все эти поля при переформатировании вывода, например:

p4 -F "just the filename please: %depotFile%" files ...

* см. также -Ztag, который дает вам альтернативный словарь полей вывода