как определить последнюю строку в awk до конца
Я пытаюсь добавить последнюю строку в файл, который я создаю. как можно обнаружить последнюю строку файла в awk до END
? мне нужно это сделать, потому что переменные не работают в END
блок,
поэтому я пытаюсь избежать использования END
.
awk ' { do some things..; add a new last line into file;}'
до END
, Я не хочу этого:
awk 'END{print "somethins new" >> "newfile.txt"}'
большое спасибо заранее..
6 ответов
один из вариантов-использовать getline
функция для обработки файла. Он возвращается 1
на успех, 0
в конце файла и -1
на ошибку.
awk '
FNR == 1 {
## Process first line.
print FNR ": " ;
while ( getline == 1 ) {
## Process from second to last line.
print FNR ": " ;
}
## 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
$ cat file
1
2
3
4
5
прочитав один и тот же файл дважды ( рекомендуется )
$ awk 'FNR==NR{last++;next}{print , ((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 , ((last==FNR)?"I am Last":"")}' file
1
2
3
4
5 I am Last
печать предыдущей строки. Когда текущая строка 2, строка печати 1, если текущая строка равна 3, выведите строку 2. .... до конца
awk '{
if (NR>1) {
# process str
print str;
}
str=;
}
END {
# process whatever needed before printing the last line and then print the last line.
print str;
}'
Вы можете получить количество строк в файл с помощью "wc -l" | getline filesize
в блоке begin и использовать NR == filesize
для проверки последней строки в теле скрипта.
можно использовать ENDFILE
, он выполняет перед END
:
$ awk 'END {print "end"} ENDFILE{print "last line"}' /dev/null /dev/null
last line
last line
end
ENDFILE существует в последней версии awk (>4.0, я думаю).
Я знаю, что ответ был принят, но это просто неправильно.
потому что вы хотите использовать awk в парсер, а не как код.
Awk должен использоваться в некоторых каналах unix, и он не должен использоваться ни в одной логике.
у меня была такая же проблема и я решил ее в awk и такой:
nlines=wc -l <file>
cat / awk-v nl=${nlines} ' {if (nl != NR) {печать $0,",","\";} else {print;}}' >> ${someout}
есть важный момент здесь: трубы, смыв и ОЗУ.
Если вы сделаете 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 ": " ;
while ( getline == 1 ) {
## Process from second to last line.
print FNR ": " ;
}
}
' x.r
#
EOF
#
chmod +x awkGetline.sh
#
cat <<"EOF" > awkPlain.sh
#! /bin/sh
#
awk '
{print FNR ": " ;}
' 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+; print , 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+; print , 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+; print , 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+; print , 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+; print , 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+; print , 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+; print , 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+; print , 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
где вы экономите около 10% времени только из-за getline.
рассмотрим это в более сложной логике, и вы можете получить даже худшую картину. В этой простой версии учет памяти не учитывается. И, кажется, они не играют роли для этой простой версии. Но память также может сыграть свою роль, если вы попадете в более сложную логику ...
конечно попробовать это на твоем автоответчике.
вот почему я предлагал рассмотреть другие варианты в целом.