Mam scenariusz, w którym wiersze będą dodawane na początku i na końcu ogromnych plików.
Próbowałem, jak pokazano poniżej.
dla pierwszego wiersza:
sed -i '1i\'"$FirstLine" $Filename
dla ostatniej linii:
sed -i '$ a\'"$Lastline" $Filename
Problem z tym poleceniem polega na tym, że dołącza on pierwszą linię pliku i przechodzi przez cały plik. W ostatnim wierszu ponownie przechodzi przez cały plik i dołącza ostatni wiersz. Ponieważ jest to bardzo duży plik (14 GB), zajmuje to bardzo dużo czasu.
Jak mogę dodać linię na początku, a drugą na końcu pliku, czytając plik tylko raz?
źródło
for
pętli:for file in Tes*; do [command]; done
"$file"
, a nieTes*
argumentued
.Pamiętaj, że jeśli chcesz uniknąć przydzielania całej kopii pliku na dysku, możesz:
Wykorzystuje to fakt, że gdy jego stdin / stdout jest plikiem,
sed
odczytuje i zapisuje blok. Więc tutaj jest OK, aby przesłonić plik, który czyta, dopóki pierwszy dodawany wiersz jest mniejszy niżsed
rozmiar bloku (powinien wynosić około 4k lub 8k).Zauważ jednak, że jeśli z jakiegoś powodu
sed
nie powiedzie się (zabity, awaria komputera ...), skończysz z plikiem w połowie przetworzonym, co będzie oznaczać brak danych w rozmiarze pierwszej linii gdzieś pośrodku.Zauważ też, że jeśli nie jesteś
sed
GNUsed
, nie będzie to działać dla danych binarnych (ale ponieważ używasz-i
, używasz GNU sed).źródło
Oto kilka opcji (z których wszystkie utworzą nową kopię pliku, więc upewnij się, że masz na to wystarczająco dużo miejsca):
proste echo / cat
awk / gawk itp
awk
i podobnie czytają pliki linia po linii.BEGIN{}
Blok jest wykonywany przed pierwszą linią iEND{}
bloku po ostatnim wierszu. Tak więc powyższe polecenie oznaczaprint "first" at the beginning, then print every line in the file and print "last" at the end
.Perl
Jest to zasadniczo to samo, co gawk powyżej właśnie napisany w Perlu.
źródło
sed -i
który tworzy pliki tymczasowe.Wolę dużo prostsze:
To przekształca plik:
do pliku:
źródło
Możesz używać Vima w trybie Ex:
1
wybierz pierwszą linięi
wstaw tekst i nowy wiersz$
wybierz ostatnią linięa
dołącz tekst i znak nowej liniix
Zapisz i zamknijźródło
Nie ma możliwości wstawienia danych na początku pliku¹, wystarczy utworzyć nowy plik, zapisać dodatkowe dane i dołączyć stare dane. Musisz więc przepisać cały plik przynajmniej raz, aby wstawić pierwszy wiersz. Możesz jednak dołączyć ostatni wiersz bez przepisywania pliku.
Alternatywnie możesz połączyć te dwa polecenia w jednym uruchomieniu sed.
sed -i
tworzy nowy plik wyjściowy, a następnie przenosi go nad starym plikiem. Oznacza to, że gdy sed działa, druga kopia pliku zajmuje więcej miejsca. Możesz tego uniknąć przez zastępując plik w miejscu , ale z poważnymi ograniczeniami: dodawana linia musi być mniejsza niż bufor sed, a jeśli system ulegnie awarii, skończy się to uszkodzeniem pliku i utratą części zawartości w pliku środkowy, więc zdecydowanie odradzam.¹ Linux ma sposób wstawiania danych do pliku, ale może wstawiać tylko całą liczbę bloków systemu plików, nie może wstawiać ciągów o dowolnej długości. Jest przydatny w niektórych aplikacjach, takich jak bazy danych i maszyny wirtualne, ale jest bezużyteczny w przypadku plików tekstowych.
źródło
fallocate()
zFALLOC_FL_INSERT_RANGE
dostępnych na ext4 i XFS w nowoczesnych jądrach (4.xx) man7.org/linux/man-pages/man2/fallocate.2.htmlźródło
Nowoczesne jądra Linuksa (wyższe niż 4.1 lub 4.2) obsługują wstawianie danych na początku pliku za pomocą
fallocate()
wywołania systemowego za pomocąFALLOC_FL_INSERT_RANGE
w systemach plików ext4 i xfs. Zasadniczo jest to logiczna operacja przesunięcia: dane są logicznie przenoszone z większym przesunięciem.Istnieje ograniczenie dotyczące ziarnistości zakresu, który chcesz wstawić na początku pliku. Ale w przypadku plików tekstowych można prawdopodobnie przydzielić nieco więcej niż jest to wymagane (do granicy ziarnistości) i wypełnić spacje lub znaki powrotu karetki, ale to zależy od aplikacji
Nie znam żadnego łatwo dostępnego narzędzia linuxowego, które manipuluje zakresami plików, ale nie jest to trudne do napisania: pobierz deskryptor pliku i wywołaj
fallocate()
z odpowiednimi argumentami. Więcej informacji można znaleźć na stronie manfallocate
wywołania systemowego: http://man7.org/linux/man-pages/man2/fallocate.2.htmlźródło
fallocate
narzędzie. Problem polega na tym, że ziarnistość całych bloków czyni to bezużytecznym dla większości plików tekstowych. Innym problemem jest to, że przydział zakresu i późniejsza modyfikacja nie są atomowe. Więc to tak naprawdę nie rozwiązuje problemu.fallocate
atomowość jest zepsuta, proszę, jestem ciekawa)