【问题标题】:Automatically modifying text files自动修改文本文件
【发布时间】:2014-08-16 08:24:05
【问题描述】:

这是我的问题:我有一个目录,其中包含来自 Oracle Instant Client 的一堆示例代码。他们每个人都演示了一个简单的数据库操作。我的目标是改变他们所有的连接顺序。

它们有两种连接方式。要么他们做

EXEC SQL CONNECT :username IDENTIFIED BY :password;

或者他们会这样做

EXEC SQL CONNECT :uid;

在第一种情况下,我们在程序的前面定义了变量

char *username = "scott";
char *password = "tiger";

每当我遇到使用这个序列的程序时,我首先想更改密码,然后我想在上面两个下面添加一行以获得以下内容

char *username = "scott";
char *password = "newPassword";
char *sqlHost = "hostid";

那我需要把上面的连接顺序(我们是情况1)改成

EXEC SQL CONNECT :username IDENTIFIED BY :password USING :sqlHost;

如果我们是情况二,那么在程序的前面我们定义变量

char *uid = "scott/tiger";

这种情况更容易处理:我需要做的就是将定义更改为

char *uid = "scott/newPassword/hostid";

我可以保持连接顺序不变。

我不是要求有人为我写这整件事,只是为了给我一些指示。我一直在阅读一些 Perl 文档以获取想法,但我不确定如何动态更改文件光标,以便可以在匹配的模式之后直接插入一行。我也不完全确定如何让一个脚本区分这两种情况(再说一次,也许我不必这样做,假设我可以编写我的模式只匹配其中一种。)

我可以解决此问题的另一种方法是将它们全部更改为使用第二种类型的序列进行连接。在这种情况下,我想我可以根据需要插入一个声明 uid 的新行,然后修改连接顺序以始终采用第二种类型的形式。我还想删除usernamepassword 的先前变量声明。

谢谢。

【问题讨论】:

    标签: perl replace scripting automation text-processing


    【解决方案1】:

    对于适合内存的文件:

    1. 'slurp' 将文件放入数组中
    2. 遍历数组的行
      • 检查每一行是否与 $usernameRe 匹配,如果匹配则保存行号
      • 检查每一行是否与 $prefixRe 匹配
        • 如果该行与 $caseOnePrefixRe 匹配,请记下行号并将其标记为案例 1
        • 否则将其标记为案例 2
        • 终止循环
    3. 根据需要使用保存的数组索引来更新(现有)行
    4. 循环遍历数组以将行写入输出
      • 如果需要,根据保存的数组索引添加适当的额外行

    对于不适合内存的文件,您必须对每个文件进行 2 次遍历,一次处理一行。

    在这种情况下,简单的正则表达式就足够了:

    use strict ;
    use warnings ;
    use Test::More ;
    
    my $usernameStr = 'char *username = "scott"' ;
    my $usernameRe = qr/char\s\*username\s=/ ;
    like( $usernameStr, $usernameRe, "username RE works" ) ;
    
    my $caseOneStr = 'EXEC SQL CONNECT :username IDENTIFIED BY :password;' ;
    my $caseTwoStr = 'EXEC SQL CONNECT :uid;' ;
    my $prefixRe = qr/EXEC\sSQL\sCONNECT\s/ ;
    like( $caseOneStr, $prefixRe, "Prefix RE works for Case 1" ) ;   
    like( $caseTwoStr, $prefixRe, "Prefix RE works for Case 2" ) ;
    
    my $caseOnePrefixRe =  qr/EXEC\sSQL\sCONNECT\s:[[:alnum:]]+\sIDENTIFIED\sBY/ ;
    like ( $caseOneStr, $caseOnePrefixRe, "Case 1 prefix RE works for Case 1" ) ;    
    unlike ( $caseTwoStr, $caseOnePrefixRe, "Case 1 prefix RE rejects Case 2" ) ;
    

    如果文件可以保存在内存中,则执行以下操作将文件读入行数组:

    my $filename = 'foo' ;
    open my $fh, "<", $filename ;
    my @lines = <$fh> ;
    close $fh ;
    

    使用带索引的“for”循环遍历行数组:

    for ( my $i = 0; $i < scalar( @lines ); $i++ ) {
        # scan &/or update $lines[$i] in this iteration
    }
    

    有关“啜饮”文件的更多信息,请参阅Perl Slurp Ease

    有关“like()”和“unlike()”的更多信息,请参阅Test::More

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 1970-01-01
      • 2010-09-12
      • 2016-11-10
      • 1970-01-01
      • 2021-07-10
      相关资源
      最近更新 更多