Я хочу удалить один или несколько конкретных номеров строк из файла. Как бы я сделал это с помощью sed?
Я хочу удалить один или несколько конкретных номеров строк из файла. Как бы я сделал это с помощью sed?
Ответы:
Если вы хотите удалить строки с 5 по 10 и 12:
sed -e '5,10d;12d' file
Это выведет результаты на экран. Если вы хотите сохранить результаты в одном файле:
sed -i.bak -e '5,10d;12d' file
Это создаст резервную копию файла file.bak
и удалит указанные строки.
Примечание. Номера строк начинаются с 1. Первая строка файла - 1, а не 0.
sed -e '5,$d' file
sed -e '5d' file
. Синтаксис есть <address><command>
; где <address>
может быть как одна строка 5
или ряд строк 5,10
, и команда d
удаляет данную строку или строки. Адреса также могут быть регулярными выражениями или знаком доллара, $
обозначающим последнюю строку файла.
Вы можете удалить отдельную строку с ее номером
sed -i '33d' file
Это удалит строку с номером 33 строки и сохранит обновленный файл.
sed -i '0,/<TARGET>/{/<NEW_VALUE>/d;}' '<SOME_FILE_NAME>'
. Спасибо!
и как хорошо
awk 'NR!~/^(5|10|25)$/' file
$ 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
не понимает аргумент option -
для обозначения стандартного ввода, поэтому вам нужно перенаправить скрипт во временный файл и очистить его, когда вы закончите, или, возможно, заменить одиночную черту /dev/stdin
или /proc/$pid/fd/1
вашей ОС (или оболочкой). ) имеет это.
Как всегда, вы можете добавить -i
перед -f
опцией иметь возможность sed
редактировать целевой файл на месте, вместо выдачи результата на стандартный вывод. На платформах * BSDish (включая OSX) вам также необходимо указать явный аргумент -i
; распространенная идиома - предоставить пустой аргумент; -i ''
,
p
вместо d
вместе с опцией -n
(она не будет работать -n
и !d
не будет работать).
Я хотел бы предложить обобщение с помощью 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 номер строки внутри текущего блока. (увидеть ниже)||
и &&
являются логическим оператором OR и AND .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 |
+-----+------+----------+------------+