31

我正在学习 awk/gawk。所以最近我只是尝试用它来解决任何问题,以获得更多的实践机会。

昨天同事问了一个问题

“如何从文件中删除第一行和最后一行”

. 我知道那sed '1d;$d' file会奏效。head/tail即使性能不佳,也可以正常工作。我告诉他sed,他很高兴。

后来,我试图写一个 awk 单行:到目前为止我得到的是:

awk 'NR>1{a[++k]=$0}END{for(i=1;i<k;i++)print a[i]}'

这会将整个文件存储在数组中,只是为了跳过最后一行。我觉得应该有一种更简单(或更好)的方法来做到这一点。

(如果没有更简单、更快或更好的方法,我会删除这个问题)

4

3 回答 3

72

这可以解决问题:

awk 'NR>2 {print last} {last=$0}'

awkprint last仅当 NR > 2 时(即除前 2 行之外的所有行)执行操作。在所有行上,它将变量last设置为当前行。因此,当awk读取第三行时,它会打印第 2 行(存储在 中last)。当它读取最后一行(第 n 行)时,它会打印第 n-1 行的内容。最终效果是打印了第 2 行到第 n-1 行。

于 2013-04-06T22:33:14.000 回答
19

让我建议另一种解决方案。如果您需要自定义 N 作为顶线和底线,您可以使用tailhead命令:

awk '{print $1}'  | head -n -1 | tail -n+2

head -n -1 - 删除最后一行

tail -n+2 - 从第二行开始输出(删除 1 行)

以下命令将从顶部和底部删除 3 行:

awk '{print $1}'  | head -n -3 | tail -n +4

实际上我们在这里甚至不需要 awk:

more | head -n -1 | tail -n +2

或者

cat | head -n -1 | tail -n +2

感谢Igor Fobia发表评论!

于 2015-10-16T01:29:45.600 回答
2

这是另一种方式,但它需要 gawk 函数长度:

awk '{firstline=2; cuttail=1; l[NR]=$0} END {for (i=firstline; i<=length(l)-cuttail; i++) print l[i]}'
于 2018-08-29T18:17:36.543 回答