替换文件中字符的最后一次出现

时间:2011-03-09 14:34:45

标签: linux awk

我有这个AWK脚本用5个换行符替换每个换页符(0x0C,12):

f=${*:-"-"}
awk 'BEGIN {FF=sprintf("%c",12); LF=sprintf("\n\n\n\n\n")}
     {i1=0;for(i2=i1+1;i2<=length($0);i2++) if(substr($0,i2,1) == FF)
     {print substr($0,i1+1,i2-i1-1) LF;  i1=i2}
      print substr($0,i1+1,length($0)-i1)}' $f

现在我要做的是在文件中替换此符号的仅最后一次出现。想不出一个直截了当的解决方案。如何检测最后一行?有什么想法吗?

AWK更可取(性能问题)。

3 个答案:

答案 0 :(得分:1)

sed '/\f/!b;:a;$!N;/\n.*\f/{h;s/\n[^\n]*$//p;s/^.*\n//;};$!ba;s/^\(.*\)\f/\1\n\n\n\n\n/' inputfile

说明:

  • /\f/!b - 如果该行不包含FF,则分支到结尾并打印
  • :a - 标签“a”
    • $!N - 如果不是最后一行,则追加下一行
    • /\n.*\f/{ - 如果新添加的行中有FF,则
      • h - 将累积的行保存在保留空间
      • s/\n[^\n]*$//p - 删除最后累积的行并打印其余部分
      • g - 从保留空间恢复累积的行数
      • s/^.*\n// - 删除除最后累积的行之外的所有内容
    • } - 如果
    • 结束
    • $!ba - 如果不是最后一行,请分支到标签“a”
  • s/^\(.*\)\f/\1\n\n\n\n\n/ - 用五个换行符替换文件中的最后一个FF

请注意,即使最后一行不在最后一行,这仍然有效。

以下是如何在AWK中执行此操作:

awk '/\f/ {
         print accum;
         accum = $0;
         next
     }
     {
         accum = accum "\n" $0
     }
     END {
         match(accum, ".*\f");
         print substr(accum, 1, RLENGTH - 1) "\n\n\n\n\n" substr(accum, RLENGTH + 1)}'
     }' inputfile

它只记忆它必须的东西。

答案 1 :(得分:0)

我不知道awk足以做到这一点,但可以使用sed

sed -e '$s/\x0C$/\x0C\x0C\x0C\x0C\x0C/' your_file

\x0C代表ascii十六进制代码0C的字符,你可能已经猜到了。

如果要修改文件上的文件,而不是将脚本的结果转储到标准输出,请添加-i参数。

答案 2 :(得分:0)

这是一个perl单行程序,它将整个内容读入内存并替换最后一个回车符:

perl -0777 -pe 's{\r([^\r]*)\z}{\n\n\n\n\n\1}' "$f"

perl -0777 -pe '
  $pos = rindex($_, "\r"); 
  substr($_, $pos, 1) = "\n\n\n\n\n" if $pos != -1
' "$f"