Я хочу видалити один або кілька конкретних номерів рядків з файлу. Як би це зробити за допомогою 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 |
+-----+------+----------+------------+