编写批量文本修改脚本

编写批量文本修改脚本

我经常发现自己试图对相当大的文件进行简单的文本操作。似乎应该有一种方法可以使用各种 Unix 文本修改工具中的一个或其他来编写脚本,但我不知道具体是如何实现的。

作为一个具体的例子,假设我有一些如下所示的源代码:

foo1 = undefined
foo2 = undefined
foo3 = foobar 7
foo4 = undefined

我想把它改成这样:

foo1 = error "foo1"
foo2 = error "foo2"
foo3 = foobar 7
foo4 = error "foo4"

好像地狱里应该有某种方法可以自动完成这种转变。显然我可以轻松地写一个程序在真正的编程语言中。但肯定有一些命令行工具可以做到这一点。 (?)

作为一个更复杂的例子,我该如何转向

foo=ABC
bar=DEF
baz=GHI
foo=123
bar=456
baz=789

进入

Magic(ABC, DEF, GHI);
Magic(123, 456, 789);

更一般地说,我应该使用哪种工具来进行此类转换?那是sed、还是awk、或者……?

答案1

这取决于具体情况。您的第一个示例可以使用 或 来sed解决awk。例如,使用awk

$ awk '
/undefined/ {printf "%s = error \"%s\"\n", $1, $1; next}
{print}
' input

其产生:

foo1 = error "foo1"
foo2 = error "foo2"
foo3 = foobar 7
foo4 = error "foo4"

或者使用sed

sed '
  /undefined/ s/\([^ ]*\) =.*/\1 = error "\1"/
' input

您的第二个示例可能更容易使用awk或一些高级语言(如 Perl 或 Python)来完成。再次,与awk

awk '
{
    split($0, parts, "=")
    items[i++] = parts[2]
}
i%3 == 0 {
    printf "Magic(%s, %s, %s)\n", items[0], items[1], items[2]
    i=0
}

' input

其产生:

Magic(ABC, DEF, GHI)
Magic(123, 456, 789)

更一般地说......我不确定是否可以提供一般性答案。这实际上取决于您想要完成的具体任务。一旦你退出,awk你就已经写一个程序在一个真正的编程语言,因此您不应该仅仅因为更高级的工具(如 Perl 或 Python 或 Ruby 或其他)功能更强大而回避它。

答案2

sed非常适合简单的文本操作 - 通常是单行编辑,尽管它可以处理多行(需要付出很大的努力)。总体而言sed,由于缺乏变量和算术计算,它相当受限制,但尽管如此,它在许多情况下确实提供了最简单的解决方案。

awk对于简单和复杂的文本操作和数字计算都非常有效,但它并不适合除此之外的事情。

对于第一个例子:

sed -E 's/^([^ ]+) = undefined$/\1 = error "\1"/' file1
awk '$3=="undefined"{ $3="error \"" $1 "\"" } {print $0}' file1

对于第二个例子,基于 =价值观要么全大写字母,要么全数字。它还对所有非 Magic 行进行分组(要删除,只需删除out[0]语句):

awk -F'=' 'BEGIN{ # split regular expressions, using `x7F` as delimiter (or any char not in the regex)  
                  n=split("^[A-Z]+$" "\x7F" "^[0-9]+$",rx,"\x7F") 
           } 
           { for( i=1;i<=n;i++ ){
                 if( $2 ~ rx[i] ){ 
                     out[i]=out[i] sprintf( (out[i] ?", " :"") "%s", $2)
                     break 
             }   } 
             if( i>n ) out[0]=out[0] $0 RS # non-matching lines 
           }
           END{ printf out[0]
                for( i=1;i<=n;i++ ){ print "Magic(" out[i] ")" }
           }' file2

答案3

我会使用 Perl,因为它是一种(相当“正常”)编程语言,围绕强大的文本操作(搜索、用正则表达式以 vi(1) 样式替换)构建。但很多人会认为我是异端,并使用 Python。两者都随任何 Linux 发行版一起分发,并且都有不错的 Windows 实现(我确信 Mac 也是如此)。 Python 的优点是它可以用来为 Fedora 等管理工具构建大部分 GUI,因此应该已经安装它。

awk(1)都是sed(1)强大的工具,但有些专一......

相关内容