【问题标题】:Batch - Remove Range/specific words批处理 - 删除范围/特定词
【发布时间】:2018-05-17 19:37:58
【问题描述】:

在 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

如果有任何帮助,我将不胜感激,在此先感谢!

【问题讨论】:

    标签: batch-file perforce changelist unshelve


    【解决方案1】:

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

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

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

    p4 -e files ...

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      (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备注;提到的字符串操作称为sub-string substitution):

      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 是相同的,但实际上在极少数情况下它们可能会有所不同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-16
        • 2021-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多