Заменить второе вхождение строки [closed]

Губка бедняка с использованием awk :

awk '{a[NR] = $0} END {for (i = 1; i <= NR; i++) print a[i]}'

Если у вас есть tac , вы также можете использовать его неправильно:

... | tac | tac

1
28.06.2016, 02:36
4 ответа

Если вы хотите удалить только все повторяющиеся строки yyyy-mm-dd, то

% sed '/^yyyy-mm-dd/,$ { n ; /^yyyy-mm-dd/d }' srcfile
Will use per-minute statistics
Stats from 2016-06-26   00:00:00 to 2016-06-26  23:59:00
yyyy-mm-dd      hh:mm:ss
6/26/2016       0:01:00
6/26/2016       0:03:00
6/26/2016       0:01:00
6/26/2016       0:01:00
6/26/2016       0:02:00
6/26/2016       0:03:00

Если вы хотите удалить все повторяющиеся строки, то это немного халтурно и неэффективно, но работает и довольно легко понимать. (Вы можете оптимизировать второй sed | grep, но так легче читать, ИМХО).

% sed -n '1,/^yyyy-mm-dd/p' srcfile ; sed '1,/^yyyy-mm-dd/d' srcfile | grep -v ^yyyy-mm-dd | sort -u
Will use per-minute statistics
Stats from 2016-06-26   00:00:00 to 2016-06-26  23:59:00
yyyy-mm-dd      hh:mm:ss
6/26/2016       0:01:00
6/26/2016       0:02:00
6/26/2016       0:03:00
3
27.01.2020, 23:13

Правильный инструмент для этого - awk. Он позволяет вам выразить логику простым способом: установите переменную seen при первом просмотре шаблона и пропустите строки, соответствующие шаблону, если он уже был замечен. Если строка не пропущена, распечатайте ее.

awk '/^yyyy-mm-dd[ \t]+hh:mm:ss$/ {if (seen) next; ++seen}
     1 {print}'

Это можно сократить, но это становится более загадочным.

awk '!(/^yyyy-mm-dd[ \t]+hh:mm:ss$/ && !(seen++))'
2
27.01.2020, 23:13
sed -e '0,/^yyyy-mm-dd\s\+hh:mm:ss$/!{/^yyyy-mm-dd\s\+hh:mm:ss$/d}'

Диапазон 0, / pattern / (функция GNU sed) совпадает до первого вхождения, поэтому 0, / pattern /! запускает содержимое {...} в оставшейся части файла, удаляя все последующие совпадения.

2
27.01.2020, 23:13

GNU ed поддерживает числовое смещение адресов регулярных выражений, поэтому вы можете адресовать диапазон от / pattern / + 1 ] в конец файла $ . Затем вы можете удалить любые строки, соответствующие одному и тому же регулярному выражению в этом диапазоне, как g // d . Наконец, напишите измененный файл и выйдите.

ed file << EOF
/^yyyy-mm-dd/+1,$ g//d
wq
EOF

или эквивалентно

 printf '/^yyyy-mm-dd/+1,$ g//d\nwq\n' | ed file
0
27.01.2020, 23:13

Теги

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