sed: Удалить строку и предшествующие строки при непервом вхождении

Кажется, он читает по одной строке вместо того, чтобы сразу считывать весь файл в память. Я провел для вас небольшой тест:

Создайте файл, содержащий 3 строки:

$ echo -e "Line 1\nLine 2\nLine 3" >> teslines.txt
$ cat testlines.txt
Line 1
Line 2
Line 3

Создайте этот небольшой скрипт:

#!/bin/bash

while read LINE; do
    echo "$LINE"
    sleep 2
done < testlines.txt

Запустите скрипт и начните добавлять новые строки:

$./readlinetest.sh
Line 1

# Somewhere around here i started adding more lines to the file:
$ echo "Line 4" >> testlines.txt
$ echo "Line 5" >> testlines.txt
$ echo "Line 6" >> testlines.txt
$ echo "Line 7" >> testlines.txt

# Output continued:
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7

Это работает примерно так же, как tail -fзапускалось на каком-то живом логе.

-1
20.10.2019, 19:42
2 ответа

Я бы использовал для этого awk:

$ cat tst.awk
(!NF) {                # blank line
    b = ""; f = 1      # empty buffer, start buffering
}
/-->/ {                # timestamp
    f = 0              # stop buffering
    if (p == $0) {     # same timestamp
        next           # discard buffer, start over
    }
    p = $0             # save timestamp
    printf "%s", b     # print buffer
}
f {                    # buffering enabled
    b = (b $0 ORS)     # buffer line
    next               # start over
}
1                      # print line

выходы:

$ awk -f tst.awk file
231
00:13:35,230 --> 00:13:37,120
- Oh, my sister got me into it.

232
00:13:37,129 --> 00:13:38,269
- Yeah?
Is that her?

234
00:13:40,049 --> 00:13:41,090
- Yeah.
4
28.01.2020, 05:07

Я думаю, что awk-версия намного лучше, но вот bash-версия просто для развлечения:)

out="";
while read line;
do
    if [ "$prevtime" != "$line" ];then
        out="${out}${line}\n";
    else
        out="$(echo -e "${out}"|head -n -2)\n";
    fi ;
    echo  "${line}" |grep -q  "\-\->" &&  prevtime=$line  ;
done <test.srt ; echo -e "$out"
0
28.01.2020, 05:07

Теги

Похожие вопросы