파일 끝의 -WOR을 VWOR로 바꿔야 합니다.
나는 열심히 노력했다
sed s/WOR/VWOR/g
그러나 이것은 파일에 새로운 빈 줄이 생길 때까지 작동하지 않습니다.
그래서 나는 사용했다
( cat FileName && echo ) | sed 's/WOR/VWOR/g'
이것은 작동합니다. 하지만 sed가 전체 파일을 읽고 있기 때문에 교체하는 데 시간이 오래 걸립니다.
답변1
파일이 새 줄로 끝나는지 확인하세요. 이는 "텍스트 파일"에 대한 요구 사항입니다.
[ -n $(tail -c1 FileName) ] && printf '\n' >> FileName
후행 줄바꿈은 필요할 때만 추가되므로 여러 번 사용해도 문제가 없으며, 마지막 문자만 확인하므로 속도가 매우 빠릅니다.
그런 다음 (현재 유효한) 마지막 줄($)을 변경합니다.
sed -ie '$s/WOR/VWOR/'
참고: 이 명령은 기호 링크를 실제 파일로 변환합니다.
답변2
글쎄요, 저는 sed/awk나 다른 방법으로 이 문제를 해결하는 방법을 모르겠습니다. 이것은 C로 작성되었으며 속도가 빠릅니다.
/*
by Hans Schou <[email protected]> 2016
Use on your own risk.
vim: ts=4 :
gcc -o replacelastline replacelastline.c && ./replacelastline WOR VWOR Filename V
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define SEARCH 1
#define REPLACE 2
#define FILENAME 3
#define VERBOSE 4
int main(int argc, char *argv[]) {
if (FILENAME >= argc) {
printf("Error, too few args. Only found %d.\n", argc);
return EXIT_FAILURE;
}
printf("argc %d.\n", argc);
int V = 0;
if (VERBOSE <= argc) {
V = 'V' == argv[VERBOSE][0] ? 1 : 0;
printf("Verbose: %d\n", V);
}
if (V) {
printf("argv[SEARCH]: %d %s\n", strlen(argv[SEARCH]), argv[SEARCH]);
printf("argv[REPLACE]: %d %s\n", strlen(argv[REPLACE]), argv[REPLACE]);
printf("argv[FILENAME]: %s\n", argv[FILENAME]);
printf("Open file: %s\n", argv[3]);
}
size_t newFileSize = 0;
FILE *fp = fopen(argv[FILENAME],"r+");
if (NULL == fp) {
fprintf(stderr, "Error open file: %s\n", argv[FILENAME]);
return EXIT_FAILURE;
} else {
char inpBuf[8192];
/* Seek to end-of-file minus buffer size */
if (0 == fseek(fp, -sizeof(inpBuf), SEEK_END)) {
/* Read buffer with last part of file */
if (sizeof(inpBuf) != fread(&inpBuf, 1, sizeof(inpBuf), fp)) {
fprintf(stderr, "Error, could not read %d bytes from '%s'\n", sizeof(inpBuf), argv[FILENAME]);
return EXIT_FAILURE;
} else {
/* In the inpBuf, search backwards where the last line start */
int i = sizeof(inpBuf)-1-1; /* one extra minus-1 if last char is '\n' */
while (i && '\n' != inpBuf[i-1]) {
--i;
}
newFileSize = ftell(fp) - sizeof(inpBuf) + i;
if (V) printf("Last line number of chars: %d\n", sizeof(inpBuf)-i);
if (V) printf("The line: '%*.*s'\n", 10, sizeof(inpBuf)-i, &inpBuf[i]);
/* Seek back in the file to where the last line starts */
if (0 == fseek(fp, -(sizeof(inpBuf)-i), SEEK_END)) {
if (V) printf("Pos start last line: %d\n", ftell(fp));
char outBuf[sizeof(inpBuf)];
int o = 0;
/* Read inpBuf and copy to outBuf. If SEARCH found replace with REPLACE */
while (sizeof(inpBuf) > i) {
if (0 != strncmp(&inpBuf[i], argv[SEARCH], strlen(argv[SEARCH]))) {
outBuf[o] = inpBuf[i];
++i;
++o;
} else {
memcpy(&outBuf[o], argv[REPLACE], strlen(argv[REPLACE]));
i += strlen(argv[SEARCH]);
o += strlen(argv[REPLACE]);
}
}
newFileSize += o;
if (V) printf("New line: '%*.*s'\n", o, o, &outBuf);
size_t bytesWritten = fwrite(&outBuf, 1, o, fp);
if (o != bytesWritten) {
fprintf(stderr, "Error, should write %d bytes, but wrote %zu bytes.\n", o, bytesWritten);
return EXIT_FAILURE;
}
}
}
}
fclose(fp);
/* if file should be smaller than before then truncate */
if (newFileSize && strlen(argv[SEARCH]) > strlen(argv[REPLACE])) {
if (V) printf("New file size: %zu\n", newFileSize);
truncate(argv[FILENAME], newFileSize);
}
}
return EXIT_SUCCESS;
}
답변3
다음을 사용하여 파일 끝의 빈 줄을 제거하고 파일에 일부 텍스트를 추가할 수 있습니다.
(sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' "${FILE_NAME}" | sed '$d' && echo "Hello") > "${NEW_FILE_NAME}"
sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'
: 파일 끝의 빈 줄을 모두 제거합니다.
sed '$d'
: 마지막 줄이 삭제됩니다.
echo "Hello"
: 텍스트가 추가됩니다.