2011-03-09 78 views
0

我有這樣的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是最好的(性能問題)。

+0

whitespace是你的朋友 – slf 2011-03-09 14:46:10

回答

0

我不知道awk足以做到這一點,但它可能與sed

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

\x0C代表與ASCII十六進制代碼0C性格正如你可能已經猜到了。

如果要修改文件上的文件,而不是將腳本的結果轉儲到標準輸出,請添加-i參數。

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" 
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 - 標籤「一」
    • $!N - 如果不是最後一行,則追加下一行
    • /\n.*\f/{ - 如果有一個FF在新附加線,然後
      • h - 保存在保持空間的累積線
      • s/\n[^\n]*$//p - 刪除最後累積線和打印其餘
      • g - 恢復從保持空間的累積線
      • s/^.*\n// - 刪除一切,除了最後的累積線
    • } - 如果最終
    • $!ba - 如果不是最後一行,分支標記「一」
  • s/^\(.*\)\f/\1\n\n\n\n\n/ - 在文件中有五個新行
將最後FF

請注意,即使最後一個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 

它僅在內存中保存它所必須。

+0

+1,很好的解釋。 – codaddict 2011-03-10 03:44:02

相關問題