0

在 perforce 中,我使用以下批处理脚本打印搁置/更改文件的列表:

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

我会很感激任何帮助,在此先感谢!

4

2 回答 2

2

您可以在p4本地执行此操作,而几乎不需要编写任何脚本。看看这篇博文:

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

您可以通过使用-e全局 opt* 运行 Perforce 消息中的字段,如下所示:

p4 -e files ...

然后,您可以在重新格式化输出时使用任何或所有这些字段,如下所示:

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

*另请参阅-Ztag它为您提供了输出字段的备用字典

于 2018-05-18T00:12:57.603 回答
1

首先,让我们看一下您的代码:

  1. 我不知道这个程序p4,但我假设它正在设置ErrorLevel. 因此,由于此值在您要阅读的代码块中更新,因此您需要使用延迟扩展,因此请放置setlocal EnableDelayedExpansion在脚本顶部并使用!ErrorLevel!而不是%ErrorLevel%. 另一种方法是替换if not !ErrorLevel!==0为,意思是if不大于且不等于,或者用更简单的方式表示if小于,但这仅适用于程序不设置负值的情况。ifnot ErrorLevel 1ErrorLevel1ErrorLevel1
  2. 即使您更正了ErrorLevel问题,由于条件命令连接运算符if,查询也永远不会执行,因为这使得以下命令仅在前一个成功的情况下执行,这意味着其退出代码1等于 0。因此,要执行该语句,请使用无条件运算符。无论如何,还有另一个条件运算符,它让以下命令仅在退出代码为非零值的情况下执行;这个可以完全取代你的状况。%%if&||if
  3. exit命令不仅退出批处理文件,它还终止cmd批处理脚本运行的命令提示符 ( ) 实例。要退出批处理文件,只能使用exit /B
  4. 您正在将ErrorLevelto设置-1exit -1。当然,您可以这样做,但通常会避免负值;1因此,让我建议一个像(by )这样的正值exit /B 1
  5. 您正在为循环list.txt的每一次迭代打开和关闭文件。这会降低整体性能。此外,如果已经存在,则数据将被附加;如果您不希望您需要在循环之前放置以最初删除文件。无论如何,要一次写入整个文件,请在循环周围放置另一对括号。然后,您可以选择是使用重定向运算符附加到现有文件,还是使用运算符覆盖它(无需先删除它)。forlist.txtdel "list.txt" 2> nulforfor>>>

所有这些导致以下改进的脚本:

(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... 通常退出代码 和ErrorLevel是相同的,但实际上在极少数情况下它们可能会有所不同。

于 2018-05-17T23:20:12.880 回答