Рассмотрите этот файл:
#!/usr/bin/env bash
cat > example_file.txt <<EOL
TITLE something
some data
some data
some data
TITLE something else
some other data
TITLE some more
some other data
some other data
some other data
TITLE extra info
some more data
some more data
EOL
Я должен добавить новый столбец что:
/^TITLE/
,В основном результат должен быть похожим:
TITLE something,4
some data,3
some data,2
some data,1
TITLE something else,2
some other data,1
TITLE some more,4
some other data,3
some other data,2
some other data,1
TITLE extra info,3
some more data,2
some more data,1
P.S. можно предположить что:
/^TITLE/
/^TITLE/
/^TITLE/
Править:
Результаты до сих пор
на файле 100 МБ:
@Yarom
time tac trial.txt | awk 'BEGIN{x=0} {x++;{if ($1 !~/^pattern/) printf "%s,%s\n",$0,x;else if ($1 ~/^pattern/) {printf "%s,%s\n",$0,x;x=0}}}' | tac > trial2.txt
real 0m0,896s
@bac0n
time awk '{ a[i++]=$0 } END { while (i--) { a[i]=a[i] "," ++j; if (a[i] ~ /^pattern/) { j=0 } }; for (i=0; i<NR; i++) { print a[i] } }' trial.txt > trial2.txt
real 0m0,830s
@oliv:
time awk -v RS='^pattern' -v FS='\n' '
{
for(i=NF-1;i>0;i--)
printf "%s,%d\n",$i,i;
printf RT
}' trial.txt > trial2.txt
real 0m2,343s
@steeldriver
time awk -vRS='\n(^pattern|$)' -F'\n' -vOFS=, '
NR>1 {$1 = "^pattern" $1}
{for(i=1;i<=NF;i++) print $i, NF-i+1}
' trial.txt > trial2.txt
real 0m1,889s
с помощью mawk вместо awk, я добираюсь:
mawk: program limit exceeded: maximum number of fields size=32767
пример example.awk
#!/bin/awk -f
{ a[i++]=[110] } END {
while (i--) {
a[i]=a[i] "," ++j
if (a[i] ~ /^TITLE/) { j=0 }
}
for (i in a) { print a[i] }
}
awk -f example.awk example.txt
Вывод
TITLE something,4
DATA some data,3
DATA some data,2
DATA some data,1
TITLE something else,2
DATA some other data,1
TITLE some more,4
DATA some other data,3
DATA some other data,2
DATA some other data,1
TITLE extra info,3
DATA some more data,2
DATA some more data,1
Мне удалось скомпилировать следующую остроту:
tac so_count.txt | awk 'BEGIN{x=0} {x++;{if ($1 != "TITLE") printf "%s,%s\n",[110],x;else if ($1 == "TITLE") {printf "%s,%s\n",[110],x;x=0}}}' | tac
я объясню немного далее:
tac
- инвертируют порядок строк (инвертируйте кошку). awk
- если первый столбец не TITLE
, совершенствуют счетчик, если TITLE
печатают текущее количество и сбрасывают назад к 0. tac
- инвертируют его назад. Результаты:
TITLE something,4
DATA some data,3
DATA some data,2
DATA some data,1
TITLE something else,2
DATA some other data,1
TITLE some more,4
DATA some other data,3
DATA some other data,2
DATA some other data,1
TITLE extra info,3
DATA some more data,2
DATA some more data,1
Удачи!
Вы могли рассматривать каждый блок как запись и каждую строку как поле - тот путь, можно свалить количество на блок или без инвертирования файла или без загрузки больше чем одного блока в память.
, поскольку Ваши блоки очерчены заголовком, а не нижним колонтитулом, немного хакерства требуется, чтобы обрабатывать первое последние записи. Лучшее, которое я могу придумать:
awk -vRS='\n(TITLE|$)' -F'\n' -vOFS=, '
NR>1 {$1 = "TITLE" $1} # replace the RS that got stripped off
{for(i=1;i<=NF;i++) print $i, NF-i+1}
' example_file.txt
Это должно быть допустимо и в gawk
и в mawk
. Я подозреваю, что это будет работать значительно быстрее в более низких издержках mawk
; gawk
скорость может быть сопоставимой при установке локали на C/POSIX т.е. LC_ALL=C awk '...'
Используя awk:
awk -v RS='TITLE ' -v FS='\n' '
{
for(i=NF-1;i>0;i--)
printf "%s,%d\n",$i,i;
printf RT
}' file
Это полагается на разделитель записей RS
и разделителя полей FS
, которые установлены установить правильное начальное значение к счетчику i
.
единственные операторы печатают каждое поле со счетчиком и рекордным разделителем RT
связанный с RS
.
Это решение имеет преимущество, чтобы только проанализировать файл однажды и не требует для помещения целого файла в память.