搜索文件中字符串的最后一次出现并追加到它

时间:2014-01-29 22:24:10

标签: linux shell sed awk append

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

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仍然会在第一次出现字符串后附加。{p> 有人可以使用shell脚本和POSIX工具吗? Perl在shell脚本中间听起来有点笨拙。

TY Sam

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

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,伙计

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

这可能适合你(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 :(得分:1)

使用的一个解决方案:

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

答案 3 :(得分:1)

使用sed

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

答案 4 :(得分:1)

这是另一个perl解决方案:

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