Думаю, вы неправильно поняли условные выражения awk
. Начало каждой строки - это условие. Это более ... awk
способ сделать это: А как насчет
awk '
/LY1/ {
tag=gensub(/_.*/,"","1",gensub(/.*LY1/,"LY1","1", $NF))
print tag
next
}
{
print
}' input.file
Первое / LY1 /
является неявным совпадением
-условием - он выполняет выражение только в том случае, если строка ввода соответствует этому регулярному выражению. Выражение начинается с замены всего в этой строке, вплоть до LY1
на LY1
, и помещает это в тег переменной. Затем он печатает тег, и оператор next
пропускает все остальные выражения для этой записи .
После этого следует безусловное выражение, которое просто печатает строку как есть - но это не будет выполнено, если предыдущее выражение было выполнено, поскольку это вызвало бы next
.
С одним подходом gawk для относительно "небольших" (по размеру) файлов:
awk 'BEGIN{ RS=""; FS="[[:space:]]+" }
{ c++;
a[c]["t"]=$1;
a[c]["s"]=substr($0,length($1)+2)
}
END {
len=length(a);
for(i=1;i<=len;i++) {
if((i+1)<=len){ printf("%s --> %s\n%s\n\n",a[i]["t"],a[i+1]["t"],a[i]["s"]) }
else { printf("%s\n%s\n",a[i]["t"],a[i]["s"]) }
}
}' file
Вывод:
00:00:10.730 --> 00:00:13.230
this presentation is delivered by the
00:00:13.230 --> 00:00:14.610
Stanford center for professional
00:00:14.610 --> 00:00:25.500
development okay so let's get started
00:00:25.500 --> 00:00:32.399
with today's material so um welcome back
00:00:32.399
to the second lecture what I want to do
С GNU sed
иtac
:
tac file | \
sed -E '/^[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}$/ { H; x; s/^\n//; s/\n/ --> /; }' | \
tac
То же самое можно было бы написать и с традиционным sed
(, т.е. без -E
), но это было бы более многословно.
С GNU awk
иtac
:
tac file | \
gawk --re-interval '
/^[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3} --> / { old = $1 }
/^[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}$/ { if(old != "") $0 = $0 " --> " old; old = $1 }
1' | \
tac
Обратите внимание, что версия awk
может обрабатывать временные интервалы, такие как 00:00:14.610 --> 00:00:25.500
, во входном файле, в то время как версия sed
их обманывает.
Также обратите внимание, что tac
можно эмулировать с помощью sed
:
sed -n '1!G; $p; h'
или вот так:
sed '1!G; h; $!d'
Однако обе формы будут загружать весь входной файл в память, поэтому они не очень эффективны.
Результат:
00:00:10.730 --> 00:00:13.230
this presentation is delivered by the
00:00:13.230 --> 00:00:14.610
Stanford center for professional
00:00:14.610 --> 00:00:25.500
development okay so let's get started
00:00:25.500 --> 00:00:32.399
with today's material so um welcome back
00:00:32.399
to the second lecture what I want to do
Для ясности кода мы используемGNU sed
:
sed -nE '
/^([0-9][0-9]:){2}[0-9]+[.][0-9]+/!{p;d;}
h;:a
$bb;n;H
/^([0-9][0-9]:){2}[0-9]+[.][0-9]+/!ba
:b
x
y/\n_/_\n/
s/^([^_]*)_(.*)_([^_]*)$/\1 ---> \3_\2/
y/\n_/_\n/
p;g;$!s/^/\n/;D
' yourfile
00:00:10.730 ---> 00:00:13.230
this presentation is delivered by the
00:00:13.230 ---> 00:00:14.610
Stanford center for professional
00:00:14.610 ---> 00:00:25.500
development okay so let's get started
00:00:25.500 ---> 00:00:32.399
with today's material so um welcome back
00:00:32.399
to the second lecture what I want to do
В приведенных ответах я вижу циклы или переходы к другим инструментам, и мне это не нравится, если в этом нет необходимости. Мне нравится один -вкладыш:
sed -E '/^[0-9:.]+$/{x;G;s/(.*)\n(.*)\n(\n)(.*)/\1 --> \4\3\2\3/p;d;};H;$!d;x'
Но давайте шаг за шагом:
^[0-9:.]+$
как расширенное регулярное выражение для строки метки времени. Этого должно быть достаточно в реальном мире, но вы можете сделать это более точным. Я использую этот шаблон в качестве адреса, поэтому все внутри пары {}
выполняется только для строк с метками времени. sed
H
старому пробелу и e x
меняем шаблон и удерживаем пробел. Таким образом, текущая временная метка уже сохраняется в пространстве хранения для следующего цикла, а все, что нам нужно, находится в пространстве шаблонов s
заменить:s/(.*)\n(.*)\n(\n)(.*)/\1 --> \4\3\2\3/
--\1
начальную метку времени, \2
текстовую строку, \3
новую строку (нам нужно это в замене, но POSIX не t определите \n
вместо ), а \4
— отметку времени окончания. Выглядит сложнее, чем есть. p
к замене s
и последующее d
удаление пространства шаблона предохраняет нас от нежелательного вывода для первой строки, когда пространство удержания было пустым. H
и x
снова измените буферы, поэтому строки, собранные в области хранения, будут напечатаны даже без метки времени закрытия Если кто-то по-прежнему считает sed
неэлегантным, я ничем не могу помочь.