如何检测在年底前awk中的最后一行(How to detect the last line in a

2019-09-21 18:22发布

我想最后一行添加到我创建文件。 这怎么可能检测到一个文件的最后一行AWK前END ? 我需要这样做,因为变数不会在工作END块,所以我尽量避免使用END

awk ' { do some things..; add a new last line into file;}'

之前END ,我不希望这样的:

awk 'END{print "something new" >> "newfile.txt"}'

Answer 1:

一种选择是使用getline函数来处理该文件。 它返回1上sucess, 0上文件的端部和-1上的错误。

awk '
    FNR == 1 {

        ## Process first line.
        print FNR ": " $0;

        while ( getline == 1 ) {
            ## Process from second to last line.
            print FNR ": " $0;
        }

        ## Here all lines have been processed.
        print "After last line";
    }
' infile

假设infile有这样的数据:

one
two
three
four
five

输出将是:

1: one                                                                                                                                                                                                                                       
2: two                                                                                                                                                                                                                                       
3: three
4: four
5: five
After last line


Answer 2:

$ cat file 
1
2
3
4
5

通过阅读相同的文件两次(推荐)

$ awk 'FNR==NR{last++;next}{print $0, ((last==FNR)?"I am Last":"")}' file file
1
2
3
4
5 I am Last

使用getline

$ awk 'BEGIN{while((getline t < ARGV[1]) > 0)last++;close(ARGV[1])}{print $0, ((last==FNR)?"I am Last":"")}' file
1
2
3
4
5 I am Last


Answer 3:

您可以使用ENDFILE ,它之前执行END

$ awk 'END {print "end"} ENDFILE{print "last line"}'  /dev/null /dev/null
last line
last line
end

ENDFILE存在于最新版本的awk(> 4.0,我认为)。



Answer 4:

打印前行。 当当前行是2,打印1行,当当前行是3,打印线2 ....,直到结束

awk '{
    if (NR>1) {
        # process str
        print str;
    }
    str=$0;
}
END {
    # process whatever needed before printing the last line and then print the last line.
    print str;
}'


Answer 5:

你可以使用一个文件的行数"wc -l" | getline filesize "wc -l" | getline filesize在开始块和使用NR == filesize来测试脚本体的最后一行。



Answer 6:

我知道答案被接受,但它是完全错误的。

因为你想AWK的解析器,而不是使用的代码。

AWK应该一些UNIX管道内使用,它不应该任何逻辑中使用。

我有同样的问题,我解决了它的awk内是这样的:

nlines = wc -l <file>

猫| AWK -v NL = $ {nlines} '{如果(NL = NR!){$打印0 “”, “\”;}其他{打印;}}' >> $ {} someout

这里有一个重要的观点:管道,冲洗和RAM。

如果您AWK吐出它的输出你可以把它管到下一个处理器。

如果你使用一个循环内函数getline,特别是,你可能看不到尽头。

函数getline只能在一定的线路上和下一行最终依赖使用。

我爱awk的,但是我们不能用它做的一切!

编辑:

对他们来说,向下投票答案,我只是想提出这个脚本:

#! /bin/sh
#
# Generate random strings
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 100000 > x.r.100000
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1000000 > x.r.1000000
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 5000000 > x.r.5000000
#
# To save you time in case
#cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 10000000 > x.r.10000000
#
# Generate awk files
cat <<"EOF" > awkGetline.sh
#! /bin/sh
#
awk '
    FNR == 1 {

        ## Process first line.
        print FNR ": " $0;

        while ( getline == 1 ) {
            ## Process from second to last line.
            print FNR ": " $0;
        }
    }
' x.r
#
EOF
#
chmod +x awkGetline.sh
#
cat <<"EOF" > awkPlain.sh
#! /bin/sh
#
awk '
    {print FNR ": " $0;}
' x.r
#
EOF
#
# x.r.100000
#
chmod +x awkPlain.sh
#
# Execute awkGetline.sh 10 times on x.r.100000
rm -f x.t
cp x.r.100000 x.r
for runInstance in 1 2 3 4 5 6 7 8 9 10;
  do
  /usr/bin/time -p -a -o x.t ./awkGetline.sh > x.1.out;
done;
#
cat x.t | grep real | awk 'BEGIN {sum=0.0} {sum=sum+$2; print $2, sum/10;} END {print "SUM Getln", sum;}' | grep SUM
#

#
# Execute awkPlain.sh 10 times on x.r.100000
rm -f x.t
cp x.r.100000 x.r
for runInstance in 1 2 3 4 5 6 7 8 9 10;
  do
  /usr/bin/time -p -a -o x.t ./awkPlain.sh > x.1.out;
done;
#
cat x.t | grep real | awk 'BEGIN {sum=0.0} {sum=sum+$2; print $2, sum/10;} END {print "SUM Plain", sum;}' | grep SUM
#

#
# x.r.1000000
#
chmod +x awkPlain.sh
#
# Execute awkGetline.sh 10 times on x.r.1000000
rm -f x.t
cp x.r.1000000 x.r
for runInstance in 1 2 3 4 5 6 7 8 9 10;
  do
  /usr/bin/time -p -a -o x.t ./awkGetline.sh > x.1.out;
done;
#
cat x.t | grep real | awk 'BEGIN {sum=0.0} {sum=sum+$2; print $2, sum/10;} END {print "SUM Getln", sum;}' | grep SUM
#

#
# Execute awkPlain.sh 10 times on x.r.1000000
rm -f x.t
cp x.r.1000000 x.r
for runInstance in 1 2 3 4 5 6 7 8 9 10;
  do
  /usr/bin/time -p -a -o x.t ./awkPlain.sh > x.1.out;
done;
#
cat x.t | grep real | awk 'BEGIN {sum=0.0} {sum=sum+$2; print $2, sum/10;} END {print "SUM Plain", sum;}' | grep SUM
#


#
# x.r.5000000
#
chmod +x awkPlain.sh
#
# Execute awkGetline.sh 10 times on x.r.5000000
rm -f x.t
cp x.r.5000000 x.r
for runInstance in 1 2 3 4 5 6 7 8 9 10;
  do
  /usr/bin/time -p -a -o x.t ./awkGetline.sh > x.1.out;
done;
#
cat x.t | grep real | awk 'BEGIN {sum=0.0} {sum=sum+$2; print $2, sum/10;} END {print "SUM Getln", sum;}' | grep SUM
#

#
# Execute awkPlain.sh 10 times on x.r.5000000
rm -f x.t
cp x.r.5000000 x.r
for runInstance in 1 2 3 4 5 6 7 8 9 10;
  do
  /usr/bin/time -p -a -o x.t ./awkPlain.sh > x.1.out;
done;
#
cat x.t | grep real | awk 'BEGIN {sum=0.0} {sum=sum+$2; print $2, sum/10;} END {print "SUM Plain", sum;}' | grep SUM
#

exit;
# To save you time in case

#
# x.r.10000000
#
chmod +x awkPlain.sh
#
# Execute awkGetline.sh 10 times on x.r.10000000
rm -f x.t
cp x.r.10000000 x.r
for runInstance in 1 2 3 4 5 6 7 8 9 10;
  do
  /usr/bin/time -p -a -o x.t ./awkGetline.sh > x.1.out;
done;
#
cat x.t | grep real | awk 'BEGIN {sum=0.0} {sum=sum+$2; print $2, sum/10;} END {print "SUM Getln", sum;}' | grep SUM
#

#
# Execute awkPlain.sh 10 times on x.r.10000000
rm -f x.t
cp x.r.10000000 x.r
for runInstance in 1 2 3 4 5 6 7 8 9 10;
  do
  /usr/bin/time -p -a -o x.t ./awkPlain.sh > x.1.out;
done;
#
cat x.t | grep real | awk 'BEGIN {sum=0.0} {sum=sum+$2; print $2, sum/10;} END {print "SUM Plain", sum;}' | grep SUM
#

当然还有第一个结果:

tmp]$ ./awkRun.sh 
SUM Getln 0.78
SUM Plain 0.71
SUM Getln 7.2
SUM Plain 6.49
SUM Getln 35.91
SUM Plain 32.92

当你保存的时间只是因为函数getline的10%左右。

考虑这个范围内更复杂的逻辑,你可能会得到哪怕最差影片。 在这个普通的版本,内存的考虑都不占。 似乎他们不为这个简单的版本发挥作用。 但内存也可能会起到一定的作用,如果你进入更复杂的逻辑...

当然,试试你的机器上。

这就是为什么我建议考虑其他的选择,一般。



文章来源: How to detect the last line in awk before END
标签: shell awk line