【问题标题】:How to grep and replace this pattern from command line?如何从命令行 grep 和替换此模式?
【发布时间】:2021-10-06 22:15:47
【问题描述】:

我有很多这样的 Python2 文件

datetime(2019, 04, 11)
datetime(2019, 10, 01)
datetime(2019, 04, 05, 1, 1)

要将此代码迁移到 Python3,我必须删除第二个和第三个日期时间参数中的前导 0。

我知道如何将 sed 用于像这样的简单模式:

sed  -e 's/01/1/g' -e 's/02/2/g' -e 's/03/3/g'  my.py

但我的模式更复杂:我应该只修改 datetime() 的第二个和第三个参数。如何使用 sed 或任何其他命令行工具来完成?

以下命令尝试使用如下简单的静态模式在代码库中查找所有要修改的字符串:

  find . -name "*.py" | xargs grep datetime |  grep '01\|02\|03\|04\|05\|06\|07'

但它也有与上面相同的问题:grep 模式不够具体 - 上面的模式不应该查看整个字符串,只能查看 datetime() 的第二个和第三个参数。

【问题讨论】:

  • sed 's/ 0/ /g'?
  • 如果sed 's/ 0/ /g' 不是您所需要的,那么edit 您的问题可以提供更真实的代表性样本输入,尤其是在datetime() 在第4 或第5 领先0s 的情况下论据。

标签: sed grep


【解决方案1】:

你可以这样做:

find . -name "*.py" | xargs -d'\n' sed -i '/datetime/s/0\([0-9]\)/\1/g'

【讨论】:

    【解决方案2】:

    对于您的特定示例,Python 的 2to3 工具很有帮助。

    您可以只关注numliteral 的转化,然后再进行转化。

    给定:

    $ cat f.py
    datetime(2019, 04, 11)
    datetime(2019, 10, 01)
    datetime(2019, 04, 05, 1, 1)
    

    你可以这样做:

    $ 2to3 -n -w --add-suffix=3 -f numliterals f.py
    RefactoringTool: Refactored f.py
    --- f.py    (original)
    +++ f.py    (refactored)
    @@ -1,3 +1,3 @@
    -datetime(2019, 04, 11)
    -datetime(2019, 10, 01)
    -datetime(2019, 04, 05, 1, 1)
    +datetime(2019, 0o4, 11)
    +datetime(2019, 10, 0o1)
    +datetime(2019, 0o4, 0o5, 1, 1)
    RefactoringTool: Writing converted f.py to f.py3.
    RefactoringTool: Files that were modified:
    RefactoringTool: f.py
    

    04 替换为0o4 现在您有了一个更具体的正则表达式目标:

    $ sed -E 's/([[:space:]]*)0o([[:digit:]]+)/\1\2/g' f.py3
    datetime(2019, 4, 11)
    datetime(2019, 10, 1)
    datetime(2019, 4, 5, 1, 1)
    

    【讨论】:

      【解决方案3】:

      这可能对你有用(GNU sed):

      sed -E 's/(datetime\([0-9]+, )0?([0-9]+, )0?([0-9]+)/\1\2\3/' file
      

      字符串datetime上的模式匹配,并且只捕获第二个和第三个参数中的非零前导数字。

      【讨论】:

        【解决方案4】:

        考虑使用\( ... \) 表达式来匹配和保存datetime(..., 部分:

        $ cat example.py | sed  -e 's/\(datetime([^,]*,[ ]*\)0/\1/g' | sed  -e 's/\(datetime([^,]*,[^,]*,[ ]*\)0/\1/g'
        datetime(2019, 4, 11)
        datetime(2019, 10, 1)
        datetime(2019, 4, 5, 1, 1)
        

        【讨论】:

        • 考虑避免使用useless cat 并将两个sed 脚本合二为一。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-31
        • 2018-10-30
        • 2013-08-04
        • 2012-12-29
        • 2013-03-02
        相关资源
        最近更新 更多