Удалить определенные номера строк из текстового файла с помощью sed?
Я хочу удалить один или несколько номеров строк из файла. Как мне это сделать с помощью sed?
Ответы
Ответ 1
Если вы хотите удалить строки с 5 по 10 и 12:
sed -e '5,10d;12d' file
Это выведет результаты на экран. Если вы хотите сохранить результаты в одном файле:
sed -i.bak -e '5,10d;12d' file
Это вернет файл в файл file.bak
и удалит указанные строки.
Примечание. Номера строк начинаются с 1. Первая строка файла - 1, а не 0.
Ответ 2
Вы можете удалить определенную одну строку со своим номером строки на файл sed -i '33d'
Это приведет к удалению строки из 33 номера строки и сохранению обновленного файла.
Ответ 3
и awk, а также
awk 'NR!~/^(5|10|25)$/' file
Ответ 4
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$
Ответ 5
Это очень часто является симптомом антипаттера. Инструмент, который произвел номера строк, вполне может быть заменен на тот, который сразу удаляет строки. Например:
grep -nh error logfile | cut -d: -f1 | deletelines logfile
(где deletelines
- полезность, которую вы себе представляете) такая же, как
grep -v error logfile
Сказав это, если вы находитесь в ситуации, когда вам действительно нужно выполнить эту задачу, вы можете создать простой sed
script из файла номеров строк. Юмористически (но, возможно, немного смутно) вы можете сделать это с помощью sed
.
sed 's%$%d%' linenumbers
Это принимает файл номеров строк, по одному на строку и производит на стандартном выходе те же номера строк с d
, которые добавляются после каждого. Это допустимый sed
script, который мы можем сохранить в файле или (на некоторых платформах) в другой экземпляр sed
:
sed 's%$%d%' linenumbers | sed -f - logfile
На некоторых платформах sed -f
не понимает аргумент параметра -
для обозначения стандартного ввода, поэтому вам необходимо перенаправить script во временный файл и очистить его, когда вы закончите, или, возможно, замените одиночная тире с /dev/stdin
или /proc/$pid/fd/1
, если ваша ОС (или оболочка) имеет это.
Как всегда, вы можете добавить -i
перед опцией -f
, чтобы sed
редактировал целевой файл вместо того, чтобы создавать результат на стандартном выходе. На * BSDish-платформах (включая OSX) вам нужно также указать явный аргумент -i
; общая идиома заключается в предоставлении пустого аргумента; -i ''
.
Ответ 6
Я хотел бы предложить обобщение с awk.
Когда файл создается блоками фиксированного размера
и строки для удаления повторяются для каждого блока,
awk может работать нормально таким образом
awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print $0}'
OriginFile.dat > MyOutputCuttedFile.dat
В этом примере размер блока равен 2000, и я хочу напечатать строки [1..713] и [1026..1029].
-
NR
- это переменная, используемая awk для хранения текущего номера строки.
-
%
дает остаток (или модуль) деления двух целых чисел:
-
nl=((NR-1)%BLOCKSIZE)+1
Здесь мы пишем в переменной nl номер строки внутри текущего блока. (см. ниже).
-
||
и &&
являются логическим оператором ИЛИ и И.
-
print $0
записывает полную строку
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 |
+-----+------+----------+------------+