【问题标题】:How to execute svn command along with grep on windows?如何在 Windows 上执行 svn 命令和 grep?
【发布时间】:2020-10-09 06:48:16
【问题描述】:

尝试在 windows 机器上执行 svn 命令并捕获相同的输出。

代码:

import subprocess

cmd = "svn log -l1 https://repo/path/trunk | grep ^r | awk '{print \$3}'"

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

'grep' is not recognized as an internal or external command,
operable program or batch file.

我明白'grep' 不是Windows 实用程序。 出现“grep”错误不被识别为内部或外部命令, 可运行的程序或批处理文件。”

它是否只限于在 Linux 上执行? 我们可以在 Windows 上执行相同的操作吗? 我的代码对吗?

【问题讨论】:

  • 要在 Windows 计算机上拥有grep,您可以使用gnuwin32。您也可以考虑使用WSL
  • Grep 是一个 GNU 程序,默认在 Linux 上可用。但也有可用的 Windows 版本,例如这里sourceforge.net/projects/unxutils 或者您可以安装Chocolatey Package Manager 并通过choco install grep 安装grep。另一种方法是在 Windows(由 Microsoft)+ Linux 映像(如 Ubuntu)上安装 WSL。然后你有一个 shell 可以访问你的常规 NTFS 文件系统但运行 Linux。
  • 此命令提示输入密码。如何自动输入密码?
  • 每个问题请限制为一个问题。应该很容易找到如何对 Subversion 使用公钥身份验证,因为这是一个非常常见的问题。

标签: python-3.x linux svn grep


【解决方案1】:

对于 Windows,您的命令将类似于以下内容 svn log -l1 https://repo/path/trunk | find "string_to_find"

你需要在windows中使用find工具才能得到和grep一样的效果。

svn --version | find "ra"
* ra_svn : Module for accessing a repository using the svn network protocol.
* ra_local : Module for accessing a repository on local disk.
* ra_serf : Module for accessing a repository via WebDAV protocol using serf.

【讨论】:

    【解决方案2】:

    使用 svn log --search FOO 而不是 grep-ing 命令的输出。

    【讨论】:

    • 我的svn副本没有这个选项,svnbook.red-bean.com/en/1.7/svn.ref.svn.c.log.html也没有
    • 它确实存在于 1.8 草案中:svnbook.red-bean.com/nightly/en/… ...但它似乎无论如何都提取了整个日志消息,这已经由 -l 1 指定。
    • @tripleee 无论如何都要升级你的 Subversion 客户端。您正在使用 非常 过时的版本。当前版本是 1.14。
    • 我停止使用 Subversion 大约有 5 个?八?十?几年前;两年前的今天,我碰巧第一次需要它,幸运地找到了一台我还安装了它的电脑。
    【解决方案3】:

    grep 和 awk 当然也可用于 Windows,但实际上不需要安装它们——代码很容易用原生 Python 替换。

    import subprocess
    
    p = subprocess.run(["svn", "log", "-l1", "https://repo/path/trunk"],
        capture_output=True, text=True)
    for line in p.stdout.splitlines():
        # grep ^r
        if line.startswith('r'):
            # awk '{ print $3 }'
            print(line.split()[2])
    

    因为我们不需要管道,只运行一个静态命令,我们可以避免shell=True。

    因为我们不想为Popen() 做必要的管道(反正你忘了),我们更喜欢subprocess.run()。使用capture_output=True,我们可以方便地在结果对象的stdout 属性中获取其输出;因为我们期望文本输出,所以我们传递 text=True(在旧的 Python 版本中,您可能需要切换到旧的、有点误导性的同义词 universal_newlines=True)。

    我猜目的是在每个修订版的输出中搜索提交者,但这会错误地抓取任何以r 开头的行上的第三个标记(因此,如果您有一个提交消息,例如“重构为使用 Python本机代码”代码将从中提取use)。一个更好的方法是从svn 请求机器可读的输出并对其进行解析(但不幸的是,它是相当笨重的 XML,所以还有另一个对你来说并不完全是微不足道的兔子洞)。或许作为中间地带实现了一种更具体的模式来查找这些行 - 或许寻找特定数量的字段,以及您知道在哪里期望它们的静态字符串。

        if line.startswith('r'):
            fields = line.split()
            if len(fields) == 13 and fields[1] == '|' and fields[3] == '|':
                print(fields[2])
    

    您还可以制作一个正则表达式以在第三个 | 分隔字段中查找日期戳,并在第四个字段中查找更改的行数。

    作为记录,来自 Subversion 的完整提交消息看起来像

    ------------------------------------------------------------------------
    r16110 | tripleee | 2020-10-09 10:41:13 +0300 (Fri, 09 Oct 2020) | 4 lines
    
    refactored to use native Python instead of grep + awk
    (which is a useless use of grep anyway; see http://www.iki.fi/era/unix/award.html#grep)
    

    【讨论】:

    • 我真的需要为这么简单的事情编写 Python 代码吗?
    • 如果您使用的是 Windows,没有什么是简单的。安装(不一定完全兼容和/或免费)通用 Unix 工具的 Windows 端口通常是必要的,但还要分心,如果你真的想在 Unix 上使用平台的那个肮脏的借口,你在做什么?优点:便携性。缺点:如果你不在 Windows 上,它就不必移植到 Windows 上。但所有事情都算在内,这不是很难编写、理解或维护的代码;并且将大部分逻辑保留在 Python 中通常更加优雅和健壮。 (另外,你未来的维护者会理解 Awk 吗?)
    • 另外,请注意这里的多个错误修复(一个是功能性的,一个仅仅是效率/优雅)。如果您不能编写正确的 Awk 但可以编写正确的 Python,那么选择应该很容易;如果你不能,可能集中精力让其中一个正确。所以不,你不必用 Python 编写它;但我相信对于大多数有这个特殊问题的人来说,它是更好的选择。
    • Windows 有 PowerShell,它也可以在 Linux 上使用。
    • 有一次我需要一个 PowerShell 命令,它的语法在版本之间发生了巨大的变化。但是,是的,如果您认为外部依赖项是一个好主意,您可以制作一个需要不同外部依赖项的脚本。同样,我建议您尽可能多地使用一种语言编写代码,并好好学习该语言。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 2011-01-21
    • 1970-01-01
    • 2021-07-03
    相关资源
    最近更新 更多