Usuń ostatnią linię z pliku w Bash
Mam plik foo.txt
, zawierający następujące wiersze:
a
b
c
Chcę prostej komendy, która spowoduje, że zawartość foo.txt
będzie:
a
b
11 answers
Za pomocą GNU sed
:
sed -i '$ d' foo.txt
Opcja -i
nie istnieje w wersji GNU sed
starszej niż 3.95, więc musisz użyć jej jako filtra z plikiem tymczasowym:
cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp
Oczywiście, w takim przypadku można również użyć head -n -1
zamiast sed
.
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
2017-01-23 21:43:29
Jest to zdecydowanie najszybsze i najprostsze rozwiązanie, szczególnie na dużych plikach:
head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt
Jeśli chcesz usunąć górną linię użyj tego:
tail -n +2 foo.txt
Co oznacza linie wyjściowe zaczynające się od linii 2.
Nie używaj sed
do usuwania linii z górnej lub dolnej części pliku - jest to bardzo wolne, jeśli plik jest duży.
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
2013-09-22 15:17:29
Miałem problem ze wszystkimi odpowiedziami tutaj, ponieważ pracowałem z ogromnym plikiem (~300GB) i Żadne z rozwiązań się nie skalowało. Oto moje rozwiązanie:
dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )
W słowach: Znajdź długość pliku, z którym chcesz skończyć (długość pliku minus długość jego ostatniej linii, używając bc
) i ustaw tę pozycję jako koniec pliku (przez dd
w jednym bajcie /dev/null
).
Jest to szybkie, ponieważ tail
zaczyna czytać od końca, a dd
nadpisze plik zamiast kopiować (i analizować) każdą linię pliku, co robią inne rozwiązania.
Uwaga: spowoduje to usunięcie linii z pliku w miejscu! Zrób kopię zapasową lub przetestuj na fałszywym pliku przed wypróbowaniem go na własnym pliku!
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
2015-05-06 19:34:09
Aby usunąć ostatnią linię z pliku bez czytania całego pliku lub przepisywania czegokolwiek , możesz użyć
tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}
Aby usunąć ostatnią linię I wydrukować ją na stdout ("pop"), możesz połączyć to polecenie z tee
:
tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})
Te polecenia mogą efektywnie przetwarzać bardzo duży plik. Jest to podobne i inspirowane odpowiedzią Yossi, ale unika korzystania z kilku dodatkowych funkcji.
Jeśli masz zamiar używać ich wielokrotnie i chcesz obsługi błędów i niektóre inne funkcje, możesz użyć polecenia poptail
tutaj:
https://github.com/donm/evenmoreutils
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
2017-02-27 13:53:49
Użytkownicy Komputerów Mac
Jeśli chcesz usunąć tylko ostatnią linię bez zmiany samego pliku wykonaj
sed -e '$ d' foo.txt
Jeśli chcesz usunąć ostatnią linię samego pliku wejściowego wykonaj
sed -i '' -e '$ d' foo.txt
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-02-05 06:26:05
Dla Użytkowników Komputerów Mac:
Na Macu, head-n -1 nie będzie działać. I starałem się znaleźć proste rozwiązanie [ bez martwienia się o czas przetwarzania], aby rozwiązać ten problem tylko za pomocą poleceń" head "i / lub" tail".
Próbowałem następującej sekwencji poleceń i byłem szczęśliwy, że mogłem rozwiązać go za pomocą polecenia "tail" [z opcjami dostępnymi na Macu]. Tak więc, jeśli jesteś na komputerze Mac i chcesz użyć tylko "tail", aby rozwiązać ten problem, możesz użyć tego polecenia:
Kot plik.txt / tail-r | tail-n +2 | tail-R
Wyjaśnienie:
1> tail - r: po prostu odwraca kolejność linii na wejściu
2> tail-n +2: wyświetla wszystkie linie zaczynające się od drugiej linii na wejściu
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-10-16 03:37:51
echo -e '$d\nw\nq'| ed foo.txt
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-01-28 06:03:49
awk 'NR>1{print buf}{buf = $0}'
Zasadniczo ten kod mówi co następuje:
Dla każdej linii po pierwszej wyświetla buforowaną linię
Dla każdej linii zresetuj bufor
Bufor jest opóźniony o jedną linię, stąd kończy się Drukowanie linii od 1 do n-1
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
2011-02-03 01:47:44
awk "NR != `wc -l < text.file`" text.file |> text.file
Ten fragment załatwia sprawę.
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-10-13 15:09:53
Oba te rozwiązania są tutaj w innych formach. Okazało się, że są trochę bardziej praktyczne, przejrzyste i przydatne: {]}
Użycie dd:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}
Użycie truncate:
BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
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
2017-11-16 16:27:06
Ruby (1.9+)
ruby -ne 'BEGIN{prv=""};print prv ; prv=$_;' file
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
2011-02-03 02:43:24