Jak usunąć określone linie (używając numerów linii) z pliku?

27

Istnieją określone wiersze, które chcę usunąć z pliku. Powiedzmy, że jest to linia 20-37, a następnie linia 45. Jak miałbym to zrobić bez określania zawartości tych linii?

tshepang
źródło
Jak duży jest twój plik? Czy można go załadować do pamięci?
Faheem Mitha,
Kilka kilobajtów.
tshepang,

Odpowiedzi:

29

Z sed:

sed '20,37d; 45d' < input.txt > output.txt

Jeśli chcesz to zrobić w miejscu:

sed --in-place '20,37d; 45d' file.txt
pdo
źródło
Czy można to zrobić na miejscu?
tshepang
Proponuję plik sed -i
enzotib
1
@Tshepang: Użyj edlub GNU sed -i, lub sponge, lub metody dużych plików .
Gilles „SO- przestań być zły”
3
Często zastanawiałem się nad potencjalnie wprowadzającym w błąd terminem w odniesieniu do „sed”, więc szukałem go w „man sed”: - in -place [= SUFFIX] This option specifies that files are to be edited in-place. GNU sed ”robi to, tworząc plik tymczasowy i wysyłanie danych wyjściowych do tego pliku zamiast na standardowe dane wyjściowe. ... Nie znam żadnego innego „sed”, ale logistyka aktualizacji „w miejscu” za pomocą edytora strumieniowego nie „oblicza” :)
Peter.O
2
Z mojego doświadczenia wynika, że ​​większość metod „w miejscu” używa pliku tymczasowego.
Faheem Mitha
5

Jeśli plik wygodnie mieści się w pamięci, możesz również użyć ed.
Polecenia są dość podobne do sedpowyższego z jedną zauważalną różnicą : musisz przekazać listę numerów / zakresów linii, które mają zostać usunięte, w porządku malejącym (od najwyższego numeru linii / zakresu do najniższego). Powodem jest to, że kiedy usuwasz / wstawiasz / dzielisz / łączysz linie ed, bufor tekstowy jest aktualizowany po każdej podkomendie, więc jeśli usuniesz niektóre linie, reszta kolejnych linii nie będzie już w tej samej pozycji w buforze, gdy następna komenda jest wykonywana. Musisz zacząć od tyłu 1 . Edycja w
miejscu :

ed -s in_file <<IN
45d
20,37d
w
q
IN

lub

ed -s in_file <<< $'45d\n20,37d\nw\nq\n'

lub

printf '%s\n' 45d 20,37d w q | ed -s in_file

Zamień wobrzęd na ,print, jeśli chcesz wydrukować wynikowe wyjście zamiast pisać do pliku. Jeśli chcesz zachować oryginalny plik nienaruszony i zapisać w innym pliku, możesz przekazać nową nazwę pliku do wkomendy obrzędowej:

ed -s in_file <<IN
78,86d
65d
51d
20,37d
w out_file
q
IN

1 Chyba że chcesz obliczyć nowe numery wierszy po każdym delete, co w tym konkretnym przypadku jest dość trywialne (po usunięciu wierszy 20-37, tj. 18 wierszy, wiersz 45 staje się wierszem 27), abyś mógł uruchomić:

ed -s in_file <<IN
20,37d
27d
w
q
IN

Jeśli jednak musisz usunąć wiele numerów / zakresów linii, praca wstecz nie jest żadnym problemem.

don_crissti
źródło
Czy qpolecenie jest przydatne na końcu? Wydaje mi się, że tak czy inaczej.
Tom Fenech
@TomFenech - nie wszystkie implementacje wychodzą tak czy inaczej (choć większość tak ... Nie mogę już znaleźć wątku, w którym to omówiono ...)
don_crissti
1

Po prostu wczytaj go do pamięci, zmień, a następnie zapisz. Możesz zrobić coś takiego

filename = "foo"
f = open(filename, 'r+')                                                                                                                                 
linenums = [1, 3]                                                                                                                                            
s = [y for x, y in enumerate(f) if x not in [line-1 for line in linenums]]                                                                                                                                          
f.seek(0)
f.write(''.join(s))
f.truncate(f.tell())
f.close()

Testowany z 5-wierszowym plikiem. Podziękowania dla http://pleac.sourceforge.net/pleac_python/fileaccess.html , patrz sekcja „Modyfikowanie pliku na miejscu bez pliku tymczasowego”. Zobacz także /programming/125703/how-do-i-modify-a-text-file-in-python

Niektóre uwagi:

  1. Można najpierw obciąć plik, a następnie napisać do niego, zamiast pisać, a następnie obciąć, jak wyżej. Jednak nie znam flagi Pythona, która pozwala czytać, a następnie robić okrojone zapisy. Ale może coś mi brakuje, ponieważ dokument nie jest tak jasny. Co prowadzi mnie do

  2. Czasami dokumenty Pythona są naprawdę do kitu. Zobacz http://docs.python.org/library/functions.html#open

    Tryby „r +”, „w +” i „a +” otwierają plik do aktualizacji (zwróć uwagę, że „w +” obcina plik).

    Czy to coś dla ciebie znaczy? Co do cholery jest „otwarte na aktualizację”?

  3. Nie wiem, czy robienie tego w Pythonie w przeciwieństwie do czegoś uniksowego, takiego jak edytor strumieni, jest lepsze. Może być bardziej przenośny, ale nie wiem, jak przenośny jest sed. Właśnie to napisałem, ponieważ czuję się bardziej komfortowo z programowaniem na niskim poziomie niż przy użyciu klasycznych narzędzi unixowych, które są dobre, jeśli robią dokładnie to, co chcesz, ale (myślę) są ogólnie mniej elastyczne.

  4. To podejście (manipulowanie plikiem w pamięci) wymienia pamięć na miejsce na dysku. Powinien działać dobrze na komputerach z kilkoma GB pamięci dla plików do kilkuset Mb. Python nie radzi sobie bardzo dobrze z łańcuchami, więc na przykład przejście na C / C ++ nieznacznie zwiększy wydajność i znacznie zmniejszy użycie pamięci.

Faheem Mitha
źródło
0

Możesz używać Vima w trybie Ex:

ex -sc '20,37d|45d|x' file
  1. d kasować

  2. x Zapisz i zamknij

Steven Penny
źródło