用awk实现尾部

时间:2012-02-01 18:36:26

标签: linux bash scripting awk tail

好吧所以在这里我正在努力使用这个awk代码,它应该模拟尾部命令

num=$1;
{
    vect[NR]=$0;

}
END{
    for(i=NR-num;i<=NR;i++)
            print vect[$i]
}

所以我想在这里实现的是由awk模拟的tail命令 例如考虑cat somefile | awk -f tail.awk 10 shoud打印文本文件的最后10行,有什么建议吗?

4 个答案:

答案 0 :(得分:5)

for(i=NR-num;i<=NR;i++)
    print vect[$i]

$表示位置参数。仅使用普通i

for(i=NR-num;i<=NR;i++)
    print vect[i]

对我有用的完整代码是:

#!/usr/bin/awk -f
BEGIN{
        num=ARGV[1];
        # Make that arg empty so awk doesn't interpret it as a file name.
        ARGV[1] = "";
}
{
        vect[NR]=$0;
}
END{
        for(i=NR-num;i<=NR;i++)
                print vect[i]
}

您可能应该向END添加一些代码来处理NR&lt; num

答案 1 :(得分:5)

所有这些答案都存储整个源文件。这是一个可怕的想法,将打破更大的文件。

这里有一种快速的方法来只存储要输出的行数(请注意,效率更高的tail总是更快,因为它不会读取整个源文件!):

awk -vt=10 '{o[NR%t]=$0}END{i=(NR<t?0:NR);do print o[++i%t];while(i%t!=NR%t)}'

更清晰(并且code golf更少):

awk -v tail=10 '
  {
    output[NR % tail] = $0
  }
  END {
    if(NR < tail) {
      i = 0
    } else {
      i = NR
    }
    do {
      i = (i + 1) % tail;
      print output[i]
    } while (i != NR % tail)
  }'

清晰易读的代码说明:

这使用modulo operator仅存储所需数量的项目(tail变量)。在解析每一行时,它存储在较旧的数组值之上(因此第11行存储在output[1]中)。

END节将增量变量i设置为零(如果我们的行数少于所需的行数)或者行数,告诉我们去哪里开始回忆保存的线条。然后我们按顺序打印保存的行。当我们返回第一个值(在我们打印完之后)时,循环结束。

如果您不关心空白if,可以用else替换i = NR / echo "foo" |awk -vt=10 …节(或我的高尔夫示例中的ternary clause)填充请求的数字的行(var marketInventoryTotalListings = (from totalListings in xe.Descendants("MARKET_INVENTORY") where (string)totalListings.Attribute("_Type") == "TotalSales" select new MarketInventoryListing() { Prior7To12Months = ( from thing in totalListings.Parent.Descendants() where (string)totalListings.Attribute("_MonthRangeType") == "Prior7To12Months" select thing.Attribute("_Count").Value ).FirstOrDefault(), }).FirstOrDefault(); 在&#34; foo&#34;)行之前将有九个空行。

答案 2 :(得分:2)

您需要将-v num=10添加到a​​wk命令行以设置num的值。从最后一个循环中的NR-num+1开始,否则最终会得到num+1行输出。

答案 3 :(得分:2)

这可能对您有用:

awk '{a=a b $0;b=RS;if(NR<=v)next;a=substr(a,index(a,RS)+1)}END{print a}' v=10