【问题标题】:scripting language to remove license preamble on files用于删除文件上的许可证序言的脚本语言
【发布时间】:2011-12-07 15:29:15
【问题描述】:

我想递归替换“blah blah blah” 在我的许可证区域中什么都没有:

#region License
blah blah blah
blah blah blah
#endregion

应该替换为

#region License
#endregion

这应该适用于我在某个目录中的所有 .cs 文件(递归)。我用 sed 试过这个,但是因为我在 Windows 上,所以我在行尾方面遇到了一些问题。如何使用 perl(或 python)或 Windows 原生的东西来做到这一点?

编辑:这是我想出的解决方案,感谢这里的所有人!:

#/bin/bash
list=`find . -name '*.cs' -o -name '*.h' -o -name '*.cpp'` 
for i in $list 
do
perl -i~ -ne 'if (/#region License/../#endregion/) {print if /#(?:end)?  region/;next};print' $i 
done

【问题讨论】:

  • 我希望这是你自己的许可证,而不是别人的......
  • 我这样做是为了避免两个分支之间的大规模合并冲突,其中所有文件的许可证文本都已更改

标签: python regex perl


【解决方案1】:

这样的?

perl -i~ -pe 'undef $_ if /^#region License$/ .. /^#endregion$/'

【讨论】:

  • 范围运算符参考供任何好奇的人参考:perldoc.perl.org/perlop.html#Range-Operators
  • 谢谢。那么,如果我的文件名为 foo.cs,我将如何调用它来覆盖 foo.cs?
  • -i~ 表示它会覆盖您的文件,但会创建备份(在您的情况下为foo.cs~
【解决方案2】:
perl -ne 'if (/#region/../#endregion/) {print if /#(?:end)?region/;next};print' file

...根据要求在输出中保留“#region license”和“#endregion”行。

【讨论】:

  • 我如何让它用更改覆盖旧文件?
  • @Jacko :要执行就地编辑,只需将开关更改为: perl -i -ne ... 如果要保留原始文件的副本(带后缀),请执行以下操作: perl -i.old -ne ...
  • 谢谢。如果文件不在当前目录中,此脚本似乎不起作用。 (我用find枚举所有cs文件)
  • @Jacko :如有必要,请指定文件的绝对路径。什么“不起作用”?怎么样?
  • 其实我需要将“#region”替换为#region License”,否则所有区域都会被删除!!
【解决方案3】:
#!/usr/bin/env python

with open('input') as fd:
    text=fd.read()

old="""#region License
blah blah blah
blah blah blah
#endregion

"""

new="""#region License
#endregion

"""

print text.replace(old,new)

添加一些os.walk 以遍历目录并将结果写入标准输出或用新内容替换原始文件。参见例如https://stackoverflow.com/a/5421671/297323

【讨论】:

  • 不错的“亲吻”解决方案;只要许可正文都是完全相同的文本,可能就足够了。如果有一堆不同的许可证,这可以很容易地扩展以替换每个!
【解决方案4】:

ex (vim -e) 或许是个不错的选择。

echo -e 'g/^#region License$/+1,/^#endregion$/-1d\nx' | ex program.cs

  • g/.../+1,/.../-1 => 查找正则表达式之间的行(+1 => 下面一行,-1 => 上面一行)
  • d => 删除
  • \n => 输入
  • x =>保存并退出

在 Windows 中,请使用:

vim -c "g/^#region License/+1,/^#endregion/-1d" +x program.cs

【讨论】:

  • 谢谢!这可行,但不能很好地扩展到大型项目。
【解决方案5】:

读取文件的行,如果行以#region开始跳过下一行,则遍历每一行,如果行以#endregion结束,则再次开始收集行,将最后一行输出到文件中,例如

def filter_lines(lines):
    newlines = []
    startmarker = '#region'
    endmarker = '#endregion'
    skip = False
    for line in lines:

        if line.startswith(startmarker):
            newlines.append(line)
            skip = True
            continue
        if line.endswith(endmarker):
            skip = False

        if not skip: newlines.append(line)

    return newli

【讨论】:

    【解决方案6】:

    python,以防许可证主体因各种不可预知的方式而不同:

    #!/usr/bin/env python
    
    with open('input') as fd:
        text=fd.read()
    
    try:
        start, rest = text.split("#region License\n", 1)
        middle, end = rest.split("#endregion\n", 1)
        print "%s\#region License\n#endregion\n%s" % (start, end)
    except ValueError:
        # didn't contain a properly formatted license:
        print text
    

    【讨论】:

      【解决方案7】:

      我会这样做:

      perl -i.orig -0777 -p -e 's/#region License.*?#endregion/#region License\n#endregion/s' test.cc
      
      • -0777 表示整个文件都会被 slurped
      • -p 使 -e 代码被 while () { ... print $_ } 块包围
      • -i.orig 进行就地编辑,并创建备份
      • 替换结束时的标志使正则表达式中的 .* 与 eol 匹配

      使用 find 确定要处理的文件

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-07
        • 1970-01-01
        相关资源
        最近更新 更多