【问题标题】:search for the last occurence of a string in a file and append to it搜索文件中最后一次出现的字符串并附加到它
【发布时间】:2014-01-29 22:24:10
【问题描述】:

我有一个包含以下命令的文件:

doadoodle <parameters> 
doadoodle <parameters>
doadoodle <parameters>
doadoodle <parameters>
wait
some more stuff
yet some more stuff
doadoodle <parameters>
doadoodle <parameters>
wait
some more stuff
yet some more stuff

我想要做的是找到“doadoodle”的最后一次出现,然后我想附加以下行:

 "rc=\$?
echo \"\$rc  is return code of last doadoodle \" 
 exit \$rc " 

最终结果将如下所示:

doadoodle <parameters> 
doadoodle <parameters>
doadoodle <parameters>
doadoodle <parameters>
wait
some more stuff
yet some more stuff
doadoodle <parameters>
doadoodle <parameters>

rc=$?
echo "$rc  is return code of last doadoodle" 
exit $rc

wait
some more stuff
yet some more stuff

我写这个好像echo要写入文件,所有不明确的字符都必须转义。

 "rc=\$?
echo \"\$rc  is return code of last doadoodle \" 
 exit \$rc " 

我试过这些都是徒劳的:

 sed '/doadoodle/{x;/./p;x;h;d};x;/./!{x;b};x;H;$!d;x;s/doadoodle[^\n]*\n/&  "my append stuff here.Note its got newlines inside it"\n/' file 

我在awk 中尝试过类似的操作,但它会在每个“doadoodle”之后打印出来。在最后一个之后我想要它。 任何线索如何做到这一点? 这是我在awk 中尝试过的:

tac file |  awk '{print} /^dooadoodle/&& !n {print "msg" ; n++}'

尽管有tac,它仍然会在字符串第一次出现之后追加。 有人可以只使用 shell 脚本和 POSIX 工具吗? Perl 在 shell 脚本中间听起来有点笨拙。

泰山

更新宝马的问题。文件格式如下:

Nohup Noodldo commands > filename 2>&1&
Nohup Noodldo commands > filename 2>&1&
Nohup Noodldo commands > filename 2>&1&
wait 
Nohup Noodldo commands > filename 2>&1&
Nohup Noodldo commands > filename 2>&1&

我将不处理这些,所以它必须找到“Nohup”的最后一个实例并粘贴之前的代码,

   rc=$?
echo "$rc  is return code of last doadoodle" 
exit $rc

,在里面。 第二个 SED 解决方案 也确实有效 - 与 AWK 一起。 TY,伙计们

【问题讨论】:

标签: linux shell sed awk append


【解决方案1】:

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

sed '/doadoodle <parameters>/,$!b;//{x;//p};//!H;$!d;x;s//&\nrc=$?\necho "$rc  is return code of last doadoodle" \nexit $rc/' file

在第一个模式之前正常打印所有行。

从第一个模式到文件末尾:

如果当前行包含模式,请检查模式的保留空间,如果存在打印则删除保留空间(除非这恰好是最后一行)。

如果当前行不包含该模式,则将其附加到保留空间并将其删除(除非它恰好是最后一行)。

当当前行是最后一行时交换到保持空间,插入需要的字符串并打印。

【讨论】:

    【解决方案2】:

    如果您的文件不是太大,那么您可以分两次完成此操作

    ### Store your text in a variable
    
    $ new_stuff='rc=$?                                                                                             
    echo "$rc  is return code of last doadoodle" 
    exit $rc'
    

    ### Use that variable in awk one-liner
    
    $ awk -v text="$new_stuff" '
      NR==FNR && /doadoodle/ { 
          last=NR; next 
      } 
      FNR==last { 
          print $0; printf "\n%s\n\n", text; next 
    }1' file file
    

    输出:

    wait
    some more stuff
    yet some more stuff
    wait
    some more stuff
    yet some more stuff
    doadoodle <parameters> 
    doadoodle <parameters>
    doadoodle <parameters>
    doadoodle <parameters>
    wait
    some more stuff
    yet some more stuff
    doadoodle <parameters>
    doadoodle <parameters>
    
    rc=$?
    echo "$rc  is return code of last doadoodle" 
    exit $rc
    
    wait
    some more stuff
    yet some more stuff
    

    【讨论】:

    • 这应该适用于实际的shell命令。我做了一个粗略的测试,一切都很好。TY
    【解决方案3】:

    一个使用的解决方案:

    perl -ne '
        if (m/doadoodle/) {
            printf qq|%s|, join q||, splice @lines;
            $flag = 1;
        }
        push @lines, $_;
        END { 
            if ( $flag ) { 
                printf qq|%s\n%s\n%s|, shift @lines, <<EOF, join q||, splice @lines;
    rc=$?
    echo "$rc  is return code of last doadoodle" 
    exit $rc
    EOF
            }
            else {
                printf qq|%s|, join q||, splice @lines;
            }
        }
    ' infile
    

    它将已处理的行保存在一个数组中,并在找到与doaddoodle 匹配的行时将其刷新到输出。在END 部分,它检查是否找到任何doadoodle 单词($flag 已检查)并插入文本。

    结果产生:

    doadoodle <parameters> 
    doadoodle <parameters>
    doadoodle <parameters>
    doadoodle <parameters>
    wait
    some more stuff
    yet some more stuff
    doadoodle <parameters>
    doadoodle <parameters>
    
    rc=0
    echo "  is return code of last doadoodle" 
    exit 
    
    wait
    some more stuff
    yet some more stuff
    

    【讨论】:

      【解决方案4】:

      使用 sed

      sed ':a;/\ndoadoodle/!{$s/doadoodle[^\n]*/&\n\nrc=$?\necho "$rc  is return code of last doadoodle" \nexit $rc\n/;N;ba}' file
      

      【讨论】:

      • 这确实适用于特定的例如上面,但文件内容的轻微变化会使搜索组件失明。ndoadoodle blah ndoadoodle blah&lt;br&gt; if you can pl tell me what this SED is doing -I t'd be an easy change ndoadoodle blah ndoadoodle blah wait ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah ndoadoodle blah wait 在上述情况下它不会找到 ndoadoodle。我很确定——这只是一个小改动。再次 TY - 现在和过去一样。
      • 您能否更新示例,对您的原始问题稍作改动?上面评论的格式都是一行,我看不出有什么区别。
      • 刚刚做了。抱歉,他们不会让您将 \n 添加到 cmets。所以所有的 cmets 看起来都像新鲜或陈旧的粥。
      【解决方案5】:

      这是另一个 perl 解决方案:

      perl -0777pe 's/(.*doadoodle[^\n]+)/$1\n\nrc=\$?\necho "\$rc  is return code of last doadoodle"\nexit \$rc\n/s' /tmp/infile
      

      【讨论】:

        猜你喜欢
        • 2018-11-04
        • 2014-02-15
        • 2014-12-02
        • 1970-01-01
        • 2014-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-23
        相关资源
        最近更新 更多