Text-Processing
有沒有辦法就地修改文件?
我有一個相當大的文件(35Gb),我想就地過濾這個文件(即我沒有足夠的磁碟空間來存放另一個文件),特別是我想 grep 並忽略一些模式 - 有沒有辦法在不使用其他文件的情況下執行此操作?
假設我想過濾掉所有包含
foo:
例如…的行
在系統呼叫級別,這應該是可能的。程序可以打開您的目標文件進行寫入而不截斷它,並開始寫入它從標準輸入讀取的內容。讀取 EOF 時,可以截斷輸出文件。
由於您要從輸入中過濾行,因此輸出文件的寫入位置應始終小於讀取位置。這意味著你不應該用新的輸出破壞你的輸入。
但是,找到一個可以做到這一點的程序是問題所在。
dd(1)
具有conv=notrunc
在打開時不截斷輸出文件的選項,但它也不會在最後截斷,將原始文件內容留在 grep 內容之後(使用類似的命令grep pattern bigfile | dd of=bigfile conv=notrunc
)由於從系統呼叫的角度來看它非常簡單,因此我編寫了一個小程序並在一個小型 (1MiB) 完整環回文件系統上對其進行了測試。它做了你想要的,但你真的想先用其他一些文件來測試它。覆蓋文件總是有風險的。
覆蓋.c
/* This code is placed in the public domain by camh */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> int main(int argc, char **argv) { int outfd; char buf[1024]; int nread; off_t file_length; if (argc != 2) { fprintf(stderr, "usage: %s <output_file>\n", argv[0]); exit(1); } if ((outfd = open(argv[1], O_WRONLY)) == -1) { perror("Could not open output file"); exit(2); } while ((nread = read(0, buf, sizeof(buf))) > 0) { if (write(outfd, buf, nread) == -1) { perror("Could not write to output file"); exit(4); } } if (nread == -1) { perror("Could not read from stdin"); exit(3); } if ((file_length = lseek(outfd, 0, SEEK_CUR)) == (off_t)-1) { perror("Could not get file position"); exit(5); } if (ftruncate(outfd, file_length) == -1) { perror("Could not truncate file"); exit(6); } close(outfd); exit(0); }
您可以將其用作:
grep pattern bigfile | overwrite bigfile
在您嘗試之前,我主要發布此內容以供其他人評論。也許其他人知道有一個程序可以做類似的事情,但經過更多的測試。