Як видалити кожен другий рядок із файлу?


25

Файл:

Data inserted into table. Total count 13
No error occurred
Data inserted into table. Total count 45
No error occurred
Data inserted into table. Total count 14
No error occurred
Data inserted into table. Total count 90
No error occurred

Очікуваний вихідний файл:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90

Я хочу, щоб результат виглядав так: кожен другий рядок буде видалений, але між рядками не буде розриву.


5
Ви хочете видалити кожен другий рядок або всі рядки, які містять "Не сталася помилка" ? Що робити, якщо у двох послідовних рядках було повідомлення "Не сталася помилка" ?
Tulains Córdova

1
@ user1598390 Я думаю ... у цьому випадку grep -v "No error occurred" fileця команда повинна спрацювати ... на що @paul відповів. У вихідному файлі не буде рядків, що містять частину "Не сталася помилка".
pmaipmui

1
Тоді назва питання вводить в оману.
Тулен Кордова

Відповіді:


36

З sed:

sed -e n\;d <file

З POSIX awk:

awk 'FNR%2' <file

Якщо у вас є старші awk(як oawk), вам потрібно:

oawk 'NR%2 == 1' <file

З ex:

$ ex file <<\EX
:g/$/+d
:wq!
EX

буде редагувати файл на місці.

  • g позначити глобальну команду
  • /$/ відповідати кожному рядку
  • +d видаліть наступний рядок
  • wq! зберегти всі зміни

Цей підхід поділяє той самий ідеал sed підходом. Видаліть кожен наступний рядок поточного рядка, починаючи з першого рядка.

З perl:

perl -ne 'print if $. % 2' <file

і perl6:

perl6 -ne '.say if $*IN.ins % 2' <file
perl6 -ne '.say if ++$ % 2' <file

Так ... його працює ... :) ... перший працює .... я також спробував другий .. його розповідь `awk: синтаксична помилка line1 awk: спасення біля рядка 1 '
pmaipmui

sed -en \; d <файл ~ Так, це працює @cuonglm ...
pmaipmui

1
Я здогадуюсь, що ви використовували n\;dзамість того, 'n;d'щоб зберегти дорогоцінний символ, але ця логіка виходить з вікна, коли ви без потреби використовуєте -eкомутатор та перенаправлення файлів <!
Том Фенек,

1
@Geek: Це лише коротша версія sed -e 'n;d', врятує вас один персонаж.
cuonglm

1
@Geek: якщо nкоманда записує простір шаблону до стандартного виводу, якщо -nвін використовувався, то замініть простір шаблону наступним рядком. Ось кожен непарний рядок буде надрукований n, парний рядок, а потім прочитаний у просторі шаблону, але видалити негайно командою` d.
cuonglm

62

Вирішити це, видаливши кожен другий рядок, може бути схильним до помилок (наприклад, коли процес іноді генерує дві значущі лінії замість однієї). Можливо, краще відфільтрувати сміття:

grep -v "No error occurred" file

Він може працювати як фільтр, ви можете додати сюди більше сміттєвих моделей і покращити результат.


9
+1 за вказівку, що іноді важливий другий рядок!
Каз Вулф

12

Відповідно до питання, з GNU sed:

sed '0~2d' file

видалить кожен другий рядок, але я хотів би запропонувати вміст рядків фільтру за ним:

sed '/Data/! d' file

або з таким же результатом

sed '/No error/d' file

sed '/ Немає помилок / d' файл ~ дає потрібний вихід @Costas
pmaipmui

5
Зауважте, що останні два - це звичні способи написання grep Dataіgrep -v 'No error'
Стефан Шазелас

5

Ось спосіб використання sed:

sed -n 'p;n' filename

Ще один спосіб з GNU sed:

sed -n '1~2p' filename

Виведення з команд вище:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90

Що ви маєте на увазі, кажучи shortest way using sed?
cuonglm

Яка причина в gкомандуванні? sed -n 'p;n'достатньо.
Костас

@cuonglm: Я хочу сказати простий спосіб виконання. До речі вилучив це слово. :)
serenesat

@Costas: Дякую! Щойно перевірено, його робота без g. видалено g з команди. :)
serenesat

4

Ви можете спробувати awk:

awk 'NR % 2 != 0' file

або ви можете друкувати лише рядки, що містять Data inserted:

awk '$0 ~ /Data inserted/' file

Я спробував обидва ви відповіді, і обидва працюють ... :)
pmaipmui

3

Ще одна відповідь, ви можете використовувати vi / vim!

qdjddq

І тоді, якщо у вашому файлі було 500 рядків (наприклад)

250 @ д

А потім записати та вийти типу

: х

Або якщо щось піде не так, і ви не хочете економити:

: q!

Пояснення:

q      #Start Recording
 d     #Put the recording into register 'd'
  j    #Move the cursor down
   dd  #Delete the line
     q #Stop recording


250    #Number of repeats
   @d  #Playback the recording in register 'd'.

2

Ось зовсім інший спосіб зробити це:

< file paste - - | cut -f1

Це передбачає, що рядки з непарними номерами не містять вкладок. Якщо це так, вам потрібно вибрати інший символ розділення, наприклад :тут:

< file paste -d: - - | cut -d: -f1

1
Я мав це на увазі, коли вперше побачив питання ... Було б цікаво провести тест на швидкість проти sedвеличезного файлу (наприклад, 20 міль рядків). У будь-якому разі, +1, але насправді, щоб уникнути головних болів, виберіть роздільник, який навряд чи виникне в текстовому файлі, наприклад $'\002'...
don_crissti

@don_crissti так, використання символу, що не друкується для роздільника, є хорошою ідеєю. І так, це помірно швидше, ніж розчин седу. Я створив тестовий файл за допомогою seq 100000000 > 100mil.txt. paste|cutРозчин закінчив приблизно 7,5 секунди, проти майже 12 для sedрозчину. Здається, що повторюється. grepАле найшвидший. Ubuntu 14.04 зі стандартними інструментами GNU.
Цифрова травма

Так, paste+ cutсильно оптимізовані для своєї роботи, тому не дивно, що їх поєднання досить
чортово


0

Це також вирішує проблему, хоча це трохи повільніше:

vim -c "%normal jdd" -c "wq" file
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.