Я хочу видалити один або кілька конкретних номерів рядків з файлу. Як би це зробити за допомогою 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 також
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аргумент параметрів не розуміє -стандартного введення, тому вам доведеться перенаправити скрипт на тимчасовий файл і очистити його, коли ви закінчите, або, можливо, замініть одиночний тире /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 номер рядка всередині поточного блоку. (Дивись нижче)||і &&є логічним оператором АБО і І .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 |
+-----+------+----------+------------+