Mam dużą liczbę plików, z których niektóre są bardzo długie. Chciałbym je przyciąć do określonego rozmiaru, jeśli są większe, usuwając koniec pliku. Ale chcę tylko usunąć całe linie. W jaki sposób mogę to zrobić? To wydaje się być czymś, co poradziłby sobie system narzędziowy Linuksa, ale nie znam właściwego polecenia.
Załóżmy na przykład, że mam plik o wielkości 120 000 bajtów z liniami o długości 300 bajtów i próbuję go skrócić do 10 000 bajtów. Pierwsze 33 wiersze powinny pozostać (9900 bajtów), a pozostałe powinny zostać wycięte. Nie chcę przecinać dokładnie 10 000 bajtów, ponieważ pozostawiłoby to częściową linię.
Oczywiście pliki mają różną długość, a linie nie są tej samej długości.
Idealnie pliki wynikowe byłyby nieco krótsze niż nieco dłuższe (jeśli punkt przerwania znajduje się na długiej linii), ale to nie jest zbyt ważne, może to być nieco dłuższe, gdyby to „łatwiejsze”. Chciałbym, aby zmiany były wprowadzane bezpośrednio w plikach (no cóż, być może nowy plik skopiowany gdzie indziej, oryginalny usunięty, a nowy plik przeniesiony, ale to samo z POV użytkownika). Rozwiązanie, które przekierowuje dane do wielu miejsc, a następnie z powrotem zachęca do uszkodzenia pliku i chciałbym tego uniknąć ...
źródło
Odpowiedzi:
sed
/wc
Złożoność można uniknąć w poprzednich odpowiedzi, jeśliawk
jest używany. Korzystając z przykładu dostarczonego z OP (pokazującego pełne linie przed 10000 bajtów):Pokazuje również pełny wiersz zawierający 10000. bajt, jeśli ten bajt nie znajduje się na końcu wiersza:
Powyższa odpowiedź zakłada:
\n
). W przypadku plików tekstowych Dos / Windows (\r\n
) zmieńlength() + 1
nalength() + 2
LC_CTYPE=C
aby wymusić interpretację na poziomie bajtów.źródło
sed
Podejście jest w porządku, ale do pętli na wszystkich liniach nie jest. Jeśli wiesz, ile wierszy chcesz zachować (aby mieć przykład, używam tutaj 99), możesz to zrobić w następujący sposób:Objaśnienie:
sed
jest procesorem wyrażeń regularnych. Z-i
podaną opcją przetwarza plik bezpośrednio („inline”) - zamiast po prostu czytać go i zapisywać wyniki na standardowym wyjściu.100,$
oznacza po prostu „od wiersza 100 do końca pliku” - po nim następuje polecenied
, które prawdopodobnie poprawnie odgadłeś jako „usuń”. Krótko mówiąc, polecenie oznacza: „Usuń wszystkie linie z linii 100 do końca pliku z mojego pliku.txt”. 100 to pierwszy wiersz do usunięcia, ponieważ chcesz zachować 99 wierszy.Edycja: Jeśli z drugiej strony istnieją pliki dziennika, w których chcesz zachować, np. Ostatnie 100 wierszy:
Co tu się dzieje:
[ $(wc -l myfile.txt) -gt 100 ]
: wykonaj następujące czynności tylko wtedy, gdy plik ma więcej niż 100 linii$((100 - $(wc -l myfile.txt|awk '{print $1}')))
: oblicz liczbę linii do usunięcia (tzn. wszystkie linie pliku oprócz (ostatnich) 100 do zachowania)1, $((..)) d
: usuń wszystkie linie od pierwszej do linii obliczonejEDYCJA: ponieważ pytanie zostało właśnie zredagowane, aby podać więcej szczegółów, do mojej odpowiedzi dołączę również te dodatkowe informacje. Dodano fakty:
Na podstawie tych danych można obliczyć liczbę linii, które pozostaną jako „/”, co w przykładzie oznaczałoby 33 linie. Termin powłoki do obliczeń:
$((size_to_remain / linesize))
(przynajmniej w systemie Linux przy użyciu Bash, wynikiem jest liczba całkowita). Skorygowane polecenie brzmiałoby teraz:Ponieważ rozmiary są znane z góry, nie ma już potrzeby wykonywania obliczeń osadzonych w
sed
poleceniu. Ale dla elastyczności w skrypcie powłoki można używać zmiennych.Do przetwarzania warunkowego opartego na rozmiarze pliku można użyć następującej „testowej” konstrukcji:
co oznacza: „jeśli rozmiar
$file
przekracza 100ls -lk
kB , wykonaj ...” ( wyświetla rozmiar pliku w kB w pozycji 5, stądawk
jest używany do wyodrębnienia dokładnie tego).źródło
head -n
.Nie mogąc znaleźć polecenia, aby to zrobić, napisałem szybki skrypt (nie przetestowany):
źródło
Możesz użyć polecenia linux sed, aby usunąć linie z pliku. Następujące polecenie usuwa ostatni wiersz pliku.txt:
Za pomocą awk lub find możesz wyszukać wzorzec pasujący do twojego polecenia sed. Najpierw wyszukaj za pomocą awk lub znajdź pliki, które chcesz skrócić, a następnie możesz usunąć linie za pomocą sed.
źródło
Zrobiłem coś podobnego z ogonem. Aby w tym przypadku zachować tylko ostatnie 10 000 wierszy:
źródło