Удалить конкретные номера строк из текстового файла с помощью sed?



Я хочу удалить один или несколько конкретных номеров строк из файла. Как бы я сделал это с помощью sed?

684   6  

6 ответов:

Если вы хотите удалить строки с 5 по 10 и 12:

sed -e '5,10d;12d' file

выводит результаты на экран. Если вы хотите сохранить результаты в тот же файл:

sed -i.bak -e '5,10d;12d' file

это создаст резервную копию файла до file.bak и удалить данной линии.

и awk также

awk 'NR!~/^(5|10|25)$/' file

вы можете удалить одну строку с ее номером строки sed-i '33d' file

это приведет к удалению строки на 33 номер строки и сохранить обновленный файл.

$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$ 

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

grep -nh error logfile | cut -d: -f1 | deletelines logfile

(где deletelines это утилита, которую вы воображаете, что вам нужно) то же самое, что и

grep -v error logfile

сказав, что, если вы находитесь в ситуации, когда вам действительно нужно, чтобы выполнить эту задачу, вы можете создать простой sed скрипт из файла номеров строк. С юмором (но возможно, немного смущенно) вы можете сделать это с sed.

sed 's%$%d%' linenumbers

это принимает файл номеров строк, по одному на строку, и производит, на стандартном выходе, те же номера строк с d добавляются после каждого. Это действительно sed скрипт, который мы можем сохранить в файл, или (на некоторых платформах) трубу в другой sed например:

sed 's%$%d%' linenumbers | sed -f - logfile

на некоторых платформах, sed -f не понимает аргумента опции - для обозначения стандартного ввода, так что у вас есть чтобы перенаправить скрипт во временный файл, и очистить его, когда вы закончите, или, возможно, заменить одинокий тире на /dev/stdin или /proc/$pid/fd/1 если ваша ОС (или оболочка) имеет это.

как всегда, вы можете добавить -i до иметь sed отредактируйте целевой файл на месте, вместо получения результата на стандартном выходе. На платформах * BSDish (включая OSX) вам нужно предоставить явный аргумент -i а также; общая идиома состоит в том, чтобы предоставить пустой аргумент; -i ''.

Я хотел бы предложить обобщение с awk.

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

awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print  }'
 OriginFile.dat > MyOutputCuttedFile.dat

в этом примере размер блока составляет 2000, и я хочу напечатать строки [1..713] и [1026..1029].

  • NR - переменная, используемая awk для хранения текущего номера строки.
  • % дает остаток (или модуль) деления двух целых чисел;
  • nl=((NR-1)%BLOCKSIZE)+1 здесь мы пишем в переменной nl номер строки внутри текущего блока. (см. ниже)
  • || и && - это логический оператор или и и.
  • print пишет полную строку

Why ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
  +1   We add again 1 because we want to restore the desired order.

+-----+------+----------+------------+
| NR  | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
|  1  |  1   |    0     |     1      |
|  2  |  2   |    1     |     2      |
|  3  |  0   |    2     |     3      |
|  4  |  1   |    0     |     1      |
+-----+------+----------+------------+

Comments

    Ничего не найдено.