【问题标题】:How do I output only a capture group with sed如何使用 sed 仅输出捕获组
【发布时间】:2022-01-14 10:14:58
【问题描述】:

我有一个输入文件


Werkzeug==2.0.2 # https://github.com/pallets/werkzeug
ipdb==0.13.9  # https://github.com/gotcha/ipdb
psycopg2==2.9.1  # https://github.com/psycopg/psycopg2
watchgod==0.7  # https://github.com/samuelcolvin/watchgod

# Testing
# ------------------------------------------------------------------------------
mypy==0.910  # https://github.com/python/mypy
django-stubs==1.8.0  # https://github.com/typeddjango/django-stubs
pytest==6.2.5  # https://github.com/pytest-dev/pytest
pytest-sugar==0.9.4  # https://github.com/Frozenball/pytest-sugar
djangorestframework-stubs==1.4.0  # https://github.com/typeddjango/djangorestframework-stubs

# Documentation
# ------------------------------------------------------------------------------
sphinx==4.2.0  # https://github.com/sphinx-doc/sphinx
sphinx-autobuild==2021.3.14 # https://github.com/GaretJax/sphinx-autobuild

# Code quality
# ------------------------------------------------------------------------------
flake8==3.9.2  # https://github.com/PyCQA/flake8
flake8-isort==4.0.0  # https://github.com/gforcada/flake8-isort
coverage==6.0.2  # https://github.com/nedbat/coveragepy
black==21.9b0  # https://github.com/psf/black
pylint-django==2.4.4  # https://github.com/PyCQA/pylint-django
pylint-celery==0.3  # https://github.com/PyCQA/pylint-celery
pre-commit==2.15.0  # https://github.com/pre-commit/pre-commit

# Django
# ------------------------------------------------------------------------------
factory-boy==3.2.0  # https://github.com/FactoryBoy/factory_boy

django-debug-toolbar==3.2.2  # https://github.com/jazzband/django-debug-toolbar
django-extensions==3.1.3  # https://github.com/django-extensions/django-extensions
django-coverage-plugin==2.0.1  # https://github.com/nedbat/django_coverage_plugin
pytest-django==4.4.0  # https://github.com/pytest-dev/pytest-django

我正在尝试使用此命令为以pytest 开头的每一行提取# 之前的部分

sed -nE "s/(^pytest.+)#/\1/p" ./requirements/local.txt

预期输出

pytest==6.2.5  
pytest-sugar==0.9.4  
pytest-django==4.4.0  

实际输出

pytest==6.2.5   https://github.com/pytest-dev/pytest
pytest-sugar==0.9.4   https://github.com/Frozenball/pytest-sugar
pytest-django==4.4.0   https://github.com/pytest-dev/pytest-django

对达到​​预期有什么帮助吗?

这些参考并没有帮助解决这个特殊问题

【问题讨论】:

  • 您只匹配到#。在它之后没有任何内容是匹配文本的一部分,因此没有更改并因此打印出来......简单的解决方法是将 # 之后的所有内容也包含在您的 RE 中。
  • 对!更改为sed -nE "s/(^pytest.+)#.*/\1/p" ./requirements/local.txt 解决了这个问题。谢谢
  • 更改为 sed -nE "s/(^pytest.+)#.*/\1/p" 可能已经解决了这个特定输入文件的问题,但是 sed 命令仍然会出现问题:当 1) 没有 # 字符时,2) 有一行中有多个# 字符。

标签: regex linux bash sed


【解决方案1】:

使用sed

sed -nE 's/^(pytest[^=]*=[^[:blank:]]*).*/\1/p' file

pytest==6.2.5
pytest-sugar==0.9.4
pytest-django==4.4.0

不过grep -o 的解决方案会更简单:

grep -o '^pytest[^=]*=[^[:blank:]]*' file

pytest==6.2.5
pytest-sugar==0.9.4
pytest-django==4.4.0

说明:

  • ^pytest:在开头匹配pytest
  • [^=]*:匹配除=之外的任何字符的0个或多个
  • =:匹配一个=
  • [^[:blank:]]*: 匹配 0 个或多个非空白字符

【讨论】:

    【解决方案2】:

    # 之后缺少正则表达式。这应该可以解决它:

    $ sed -nE "s/(^pytest.+)#.*/\1/p" ./requirements/local.txt
    

    【讨论】:

    • 尽管 OP 的示例没有显示,但属性文件可能有也可能没有在每一行中以 # 开头的注释部分。此命令假定# 将始终存在。因此,仅与 pytest==124 有一行将不会匹配
    • 注:这也将捕获# 之前的空白,可能是sed -nE 's/(^pytest\S+)\s*#.*/\1/p' file
    • 除了@anubhava 的评论,如果一行中有多个# 字符,您的正则表达式将捕获部分评论。
    • 对于更通用的方法,请查看其他答案。我的只是指出了他在他的特殊案例中遗漏了什么。
    【解决方案3】:

    第一种解决方案:使用awk,您可以尝试关注。在这里使用awkmatch 函数,在GNU awk 中编写和测试应该可以在任何任何地方工作。简单的解释是,使用awkmatch 函数匹配正则表达式^pytest[^ ]* 以匹配pytest 的起始值,直到第一次出现空格,并使用substrawk 函数打印匹配的值。

    awk 'match($0,/^pytest[^ ]*/){print substr($0,RSTART,RLENGTH)}' Input_file
    

    第二个解决方案: 使用 GNU awk 尝试使用它的 RS 变量。

    awk -v RS='(^|\n)pytest[^ ]*' 'RT{sub(/^\n*/,"",RT);print RT}' Input_file
    

    【讨论】:

      【解决方案4】:

      作为使用awk 的替代方法,您还可以将字段分隔符设置为#,前面带有可选空格,如果第一列以pytest 开头,则打印第一列

      awk -F"[[:blank:]]*#" '/^pytest/ {print $1}' ./requirements/local.txt
      

      输出

      pytest==6.2.5
      pytest-sugar==0.9.4
      pytest-django==4.4.0
      

      如果# 并不总是存在,您还可以使匹配更具体以匹配数字,然后打印第一个字段:

      awk '/^pytest[^[:blank:]]*==[0-9]+(\.[0-9]+)*/ {print $1}' file
      

      【讨论】:

        【解决方案5】:

        使用sed

        $ sed -n '/^pytest/s/#.*//p' input_file
        pytest==6.2.5
        pytest-sugar==0.9.4
        pytest-django==4.4.0
        

        【讨论】:

          【解决方案6】:

          sed 单行将是:

          sed -e '/^pytest/!d' -e 's/[[:blank:]]*#.*//' file
          

          第一个表达式删除不以pytest 开头的行。第二个删除评论部分(包括# 之前的空白),如果有的话。

          【讨论】:

            猜你喜欢
            • 2011-02-16
            • 1970-01-01
            • 2020-02-11
            • 1970-01-01
            • 2023-03-07
            • 1970-01-01
            • 1970-01-01
            • 2018-07-23
            • 2016-08-22
            相关资源
            最近更新 更多