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?


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

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.


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.


0

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

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

  2. x Zapisz i zamknij

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.