Как удалить повторяющиеся строки из файла с помощью awk / sed? - PullRequest
0 голосов
/ 02 ноября 2019

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

file.txt

TIMESTEP
101
NUMBER OF ATOMS
3
ATOMS x y z
O 1 2 3
H 2 1 3
C 1 1 2
TIMESTEP
102
NUMBER OF ATOMS
3
ATOMS x y z
TIMESTEP
103
NUMBER OF ATOMS
3
ATOMS x y z
O -1 2 3
H  1 2 3
C  0 1 1
...

Я хотел бы получить

file.txt

TIMESTEP
101
NUMBER OF ATOMS
3
ATOMS x y z
O 1 2 3
H 2 1 3
C 1 1 2
TIMESTEP
103
NUMBER OF ATOMS
3
ATOMS x y z
O -1 2 3
H  1 2 3
C  0 1 1
...

Я пытался

sed '/3.*/{:a;N;N;N;N;/.*NUMBER OF ATOMS$/d;ba}' file.txt

но это также удалит допустимые кадры, что не , что я хочу. Любые указатели и советы высоко ценятся!

Ответы [ 4 ]

2 голосов
/ 02 ноября 2019

Это может работать для вас (GNU sed):

sed -n '/TIMESTEP/!{H;$!d};x;s/\n/&/5p' file

Собирать кадры (записи) в области удержания и печатать их, только если они имеют длину 6 или более строк.

1 голос
/ 02 ноября 2019

С GNU sed это будет просто:

sed -z 's/TIMESTEP\n[0-9]*\nNUMBER OF ATOMS\n[0-9]*\nATOMS x y z\nTIMESTEP/TIMESTEP/g' file.txt

Без опции -z sed, похоже, сработает следующее:

sed -n '
  # buffor 6 (not 5!, so one too much) lines into pattern space
    N;N;N;N;N

    : again

    # if pattern space matches empty frame
        /^TIMESTEP\n[0-9]*\nNUMBER OF ATOMS\n[0-9]*\nATOMS x y z\nTIMESTEP$/{
            # print just the next TIMESTEP
            s/.*/TIMESTEP/
            p
            # start from the top
            d
        }

        # if this is the last line
        ${
            # if last line is an empty frame
            /^[^\n]*\nTIMESTEP\n[0-9]*\nNUMBER OF ATOMS\n[0-9]*\nATOMS x y z$/{
                # print the line we have too much
                P
                # and end it
                d
            }

            # print until end of line
            p
            d
        }

    # just print and delete one line
        P
        s/^[^\n]*\n//
        # read next line
        N

    b again

'
1 голос
/ 02 ноября 2019

Это gnu awk может делать:

awk -v RS=TIMESTEP  'NF>15 {print RS$0}' file
TIMESTEP
101
NUMBER OF ATOMS
3
ATOMS x y z
O 1 2 3
H 2 1 3
C 1 1 2

TIMESTEP
103
NUMBER OF ATOMS
3
ATOMS x y z
O -1 2 3
H  1 2 3
C  0 1 1
...

При установке селектора записи на TIMESTEP он работает в режиме блока, каждый блок начинается с TIMESTEP. Затем посчитайте количество полей (возможно, потребуется настроить). Если его больше 15 (как минимум 9 должно быть в порядке), выведите блок

0 голосов
/ 02 ноября 2019

с GNU awk:

awk '{a[i++]=$0}END{ for(i=0;i<NR;)if(a[i]=="TIMESTEP" && a[i+5]=="TIMESTEP") {i=i+5;} else {print a[i]; i=i+1;} }' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...