【问题标题】:Sed and awk applicationsed 和 awk 应用程序
【发布时间】:2013-02-23 22:22:14
【问题描述】:

我已经阅读了一些关于 sed 和 awk 的内容,并且了解它们都是文本操纵器。

我计划使用其中一个来编辑文件组(某些编程语言、js、python 等的代码),以对大量文件进行类似的更改。 目前主要是编辑函数定义(传递的参数)和变量名,但我可以做得越多越好。

我想知道是否有人尝试过类似的事情,那些尝试过的人是否有任何明显的陷阱需要注意?以及 sed 和 awk 中的哪一个更适合/更适合这种应用程序。 (或者可能是完全不同的东西?)

输入

function(paramOne){
//Some code here
var variableOne = new ObjectType;
array[1] = "Some String";
instanceObj = new Something.something;
}

输出

function(ParamterOne){
//Some code here
var PartOfSomething.variableOne = new ObjectType;
sArray[1] = "Some String";
var instanceObj = new Something.something
}

【问题讨论】:

  • 哪个更合适很大程度上取决于您正在执行的文本操作。 awk 对于某些任务会更好,sed 对于其他任务会更好。您可能最终会同时使用这两种方法。
  • 你为什么不向我们展示你想要做什么?包括一些输入和预期输出。您的问题很大程度上取决于您实际尝试做什么。
  • 是的,这绝对是可能的,但不是一项简单的任务,而且极端情况会让人更加沮丧。通过amazon.com/s/… 阅读和工作所花费的时间将得到很好的回报。祝你好运。
  • awk 可以比任何其他脚本语言更简洁地做到这一点,但是无论您为转换选择哪种脚本语言,为您的文件编写的语言编写解析器都将非常困难。与尝试编写工具相比,手动更改文件可能更快、更不容易出错。
  • 我看到各种 cmets 对工具的适用性有些混淆。 sed 是对单行文本进行简单更改的出色工具。它有许多其他永远不应该使用的语言结构。 awk 是一种简洁、功能齐全的工具/脚本语言,适用于所有其他文本操作。 bash 是一种环境/脚本语言,用于调用工具并操作文件和进程。因此,如果您需要对多个文件中的文本进行非平凡的操作,请在 awk 中简洁地编写文本处理,在 bash 中简洁地编写文件查找/更新/调用 awk。

标签: sed awk batch-processing


【解决方案1】:

这是一个 GNU awk(用于“gensub()”函数)脚本,它将您的示例输入文件转换为您想要的输出文件:

$ cat tst.awk
BEGIN{ sym = "[[:alnum:]_]+" }
{
   $0 = gensub("^(" sym ")[(](" sym ")[)](.*)","\\1(ParameterOne)\\3","")
   $0 = gensub("^(var )(" sym ")(.*)","\\1PartOfSomething.\\2\\3","")
   $0 = gensub("^a(rray.*)","sA\\1","")
   $0 = gensub("^(" sym " =.*)","var \\1","")

   print
}

$ cat file
function(paramOne){
//Some code here
var variableOne = new ObjectType;
array[1] = "Some String";
instanceObj = new Something.something;
}

$ gawk -f tst.awk file
function(ParameterOne){
//Some code here
var PartOfSomething.variableOne = new ObjectType;
sArray[1] = "Some String";
var instanceObj = new Something.something;
}

但请考虑一下您的实际输入会如何变化 - 您可以在符号之间有更多/更少/不同的间距。您可以从一行开始分配,然后在下一行完成。您可以让 cmets 包含与您不想更改的代码相似的行。您可以在一行上有多个语句。等等等等。

您可以一次解决每个问题,但这可能比仅更新文件要花更长的时间,而且您可能仍然无法完全正确。

如果您的代码结构非常好并且严格遵循特定的、高度限制性的编码格式,那么您可以使用脚本语言做您想做的事情,但最好的选择是:

  1. 如果文件少于 10,000 个,则手动更改文件,或者
  2. 获取用于编写文件的语言的解析器(例如编译器),并对其进行修改以输出更新后的代码。

【讨论】:

    【解决方案2】:

    一旦它开始变得稍微复杂一些,无论如何你都会切换到脚本语言。那么为什么不首先从 python 开始呢?

    步行目录: walking along and processing files in directory in python

    替换文件中的文本: replacing text in a file with Python

    Python 正则表达式方法: http://docs.python.org/dev/howto/regex.html

    我还建议安装 Eclipse + PyDev,因为这将使调试更容易。

    这是一个简单的自动替换器的示例

    import os;
    import sys;
    import re; 
    import itertools;
    
    folder = r"C:\Workspaces\Test\";
    skip_extensions = ['.gif', '.png', '.jpg', '.mp4', ''];
    substitutions = [("Test.Alpha.", "test.alpha."), 
                     ("Test.Beta.", "test.beta."),
                     ("Test.Gamma.", "test.gamma.")];
    
    for root, dirs, files in os.walk(folder):
        for name in files:
            (base, ext) = os.path.splitext(name);
            file_path = os.path.join(root, name);
            if ext in skip_extensions: 
                print "skipping", file_path;
            else:
                print "processing", file_path;
    
                with open(file_path) as f:
                    s = f.read();
    
                before = [[s[found.start()-5:found.end()+5] for found in re.finditer(old, s)] for old, new in substitutions];
                for old, new in substitutions:
                    s = s.replace(old, new);
                after = [[s[found.start()-5:found.end()+5] for found in re.finditer(new, s)] for old, new in substitutions];
    
                for b, a in zip(itertools.chain(*before), itertools.chain(*after)):
                    print b, "-->", a;
    
                with open(file_path, "w") as f:
                    f.write(s);
    

    【讨论】:

    • 对于简单的文本处理来说,使用 perl 或 python 等成熟的编程/脚本语言是不必要的。 sed、awk 和 bash 的简单组合还不够吗?
    • “sed、awk 和 bash 的简单组合”通常比脚本解决方案更复杂、更难维护。关键是脚本语言有调试器,而众所周知,shell 脚本更难调试。
    • 如果您使用 python 或其他脚本语言尝试过类似的事情,我请求您将其添加到您的答案中。
    • Udo,我已经熟悉 python 中的正则表达式、目录遍历和替换,我希望向实际尝试像这样批量编辑代码文件的人学习。
    • 我经常这样做。我不明白的是:如果您熟悉这种技术,为什么需要代码示例?
    猜你喜欢
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 2012-01-24
    • 1970-01-01
    • 2016-10-30
    • 2013-06-18
    相关资源
    最近更新 更多