Usunąć określone numery linii z pliku tekstowego za pomocą sed?

Chcę usunąć jeden lub więcej konkretnych numerów linii z pliku. Jak miałbym to zrobić używając sed?

Author: Justin Ethier, 2010-01-21

6 answers

Jeśli chcesz usunąć linie od 5 do 10 i 12:

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

Spowoduje wydrukowanie wyników na ekranie. Jeśli chcesz zapisać wyniki do tego samego pliku:

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

Spowoduje powrót pliku do file.bak i usunięcie podanych linii.

 290
Author: Brian Campbell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-21 20:12:07

I awk również

awk 'NR!~/^(5|10|25)$/' file
 26
Author: ghostdog74,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-22 00:57:09

Możesz usunąć konkretny pojedynczy wiersz z jego numerem linii przez sed-i ' 33D ' plik

Spowoduje to usunięcie linii na 33 numerze linii i zapisanie zaktualizowanego pliku.

 25
Author: amit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-25 05:40:49
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$ 
 15
Author: Matthew Slattery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-21 20:12:09

Jest to bardzo często objaw antypaternu. Narzędzie, które wytworzyło numery linii, można zastąpić narzędziem, które natychmiast usuwa linie. Na przykład;

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

(gdzie deletelines jest narzędziem, które sobie wyobrażasz, czego potrzebujesz) jest taki sam jak

grep -v error logfile

Powiedziawszy to, jeśli jesteś w sytuacji, w której naprawdę musisz wykonać to zadanie, możesz wygenerować prosty skrypt sed z pliku numerów linii. Humorystycznie (ale może nieco myląco) ty można to zrobić za pomocą sed.

sed 's%$%d%' linenumbers

To przyjmuje Plik z numerami linii, po jednym na linię, I tworzy, na standardowym wyjściu, te same numery linii z d dołączane po każdym z nich. Jest to poprawny skrypt sed, który możemy zapisać do pliku lub (na niektórych platformach) przenieść do innej instancji sed:

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

Na niektórych platformach sed -f nie rozumie argumentu opcji - oznaczającego standardowe wejście, więc musisz przekierować skrypt do pliku tymczasowego i wyczyścić go, gdy gotowe, a może zastąp lone dash /dev/stdin lub /proc/$pid/fd/1 Jeśli Twój system operacyjny (lub powłoka) tak ma.

Jak zawsze, możesz dodać -i przed opcją -f, Aby sed edytował plik docelowy w miejscu, zamiast generować wynik na standardowym wyjściu. Na platformach * BSDish (w tym OSX) musisz również podać jawny argument -i; powszechnym idiomem jest podanie pustego argumentu; -i ''.

 4
Author: tripleee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 05:45:28

Chciałbym zaproponować uogólnienie za pomocą awk.

Gdy plik jest tworzony przez bloki o ustalonym rozmiarze a linie do usunięcia są powtarzane dla każdego bloku, awk może działać dobrze w taki sposób

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

W tym przykładzie rozmiar bloku wynosi 2000 i chcę wydrukować linie [1..713] i [1026..1029].

  • NR jest zmienną używaną przez awk do przechowywania bieżącego numeru linii.
  • % daje pozostałość (lub moduł) podziału dwóch liczby całkowite;
  • nl=((NR-1)%BLOCKSIZE)+1 tutaj zapisujemy zmienną nl numer linii wewnątrz bieżącego bloku. (patrz niżej)
  • || i && są operatorem logicznym lub oraz oraz.
  • print $0 pisze pełną linię

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      |
+-----+------+----------+------------+

 2
Author: Hastur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-24 14:07:54