2012-08-29 19 views
9

Zapytałem o numer question dotyczący pojawienia się ostatniej linii pliku tekstowego w PHP, a teraz, czy jest możliwe ponowne napisanie logiki w skrypcie powłoki?powłoka: usuń ostatnią linię z ogromnego pliku logu tekstowego

Próbowałem to, aby uzyskać ostatnią linię:

tail -n 1 my_log_file.log 

ale nie jestem pewien, w jaki sposób mogę usunąć ostatni wiersz i zapisz plik.

P.S. biorąc pod uwagę, że korzystam z serwera Ubuntu.

Odpowiedz

9

(rozwiązanie oparte jest na sch's answer więc kredyt powinien udać się do niego/niej)

Podejście to pozwoli Ci efektywnie odzyskać ostatnią linię pliku i obcina plik do usunięcia tej linii. To może lepiej radzić sobie z dużymi wejściami, ponieważ plik nie jest odczytywany sekwencyjnie.

# retrieve last line from file 
LAST=$(tail -n 1 my_log_file.log) 

# truncate file 
let TRUNCATE_SIZE="${#LAST} + 1" 
truncate -s -"$TRUNCATE_SIZE" my_log_file.log 

# ... $LAST contains 'popped' last line 

Należy pamiętać, że to nie będzie działać zgodnie z oczekiwaniami, jeśli plik jest modyfikowany między połączeniami do tail i truncate.

+1

Należy zauważyć, że w przeciwieństwie do „wc” rozwiązania opartego dałem która będzie działać na systemach GNU, powyższe będzie działać poprawnie tylko z zsh jeżeli ostatnia linia zawiera znaki NUL. Ponadto nie będzie działać poprawnie, jeśli ostatnia linia nie zostanie zakończona. –

+0

Również 'truncate' spodziewa rozmiar w _bytes_, podczas gdy' $ {# LAST} 'oblicza długość' $ LAST' w liczbie znaków. Chcesz ustawić ustawienia regionalne na C, aby było to równoważne. W przeciwnym razie nie działałoby to poprawnie, gdyby ostatnia linia zawierała znaki wielobajtowe. –

4

Jednym ze sposobów jest:

sed '$d' <f1> f2 ; mv f2 f1 
+0

Nie rozumiem tego. czym jest 'f2' i' f1'? – Raptor

+0

Spóźniłem się tutaj, ale to jest moje ulubione rozwiązanie. Można to zrobić zmianę w miejscu za pomocą „-i” Flag SED: „sed -i -e«$ d»my_log_file.log” –

+0

Uważaj na wykorzystaniu '-i' jeśli piszesz skrypty cross-platform, jak to inny na macOS i Linux. – bfontaine

27

Aby uzyskać zawartość pliku bez ostatniego wiersza, można użyć

head -n-1 logfile.log 

(nie jestem pewien, że ten jest wspierany wszędzie)

lub

sed '$d' logfile.log 
+0

Perfecto !!!! nice one – Satish

+1

Sed działa idealnie! $ d to polecenie kończące się przed ostatnim wierszem, dlatego może pominąć ostatnią linię! Zobacz https://www.gnu.org/software/sed/manual/sed.html. – nothize

15

Co chcesz, to skrócić plik tuż przed ostatnią linią bez konieczności całkowitego czytania tego pliku.

truncate -s -"$(tail -n1 file | wc -c)" file 

Zakładamy, że plik nie jest obecnie zapisywany.

truncate jest częścią GNU coreutils (tak ogólnie można znaleźć na ostatnich dystrybucjach Linuksa) i nie jest standardowym poleceniem Unix lub POSIX. Do skracania pliku można również użyć wielu implementacji "dd".

+0

Użycie 'tail' +' truncate' byłoby rzeczywiście bardziej wydajnym rozwiązaniem.Oczywiście, aby OP mógł pobrać zawartość ostatniego wiersza 'tail -n' powinien być wywołany oddzielnie i zapisany w var. Następnie możesz użyć '$ {# VAR} + 1' jako rozmiaru obcięcia. –

+0

Dodano [odpowiedź wiki] (http://stackoverflow.com/questions/12176492/shell-delete-the-last-line-o-uge-text-log-file/12176634#12176634) z proponowanymi zmianami. –

+3

Wygląda na to, że występuje dodatkowa kombinacja poprzedzająca ogon/wc. Możesz również użyć opcji '-r' (użyj rozmiaru podanego pliku):' truncate -r <(plik -n1-tail) file', jeśli nie masz nic przeciwko baszemu. – chepner

Powiązane problemy