UNIX: 파일의 마지막 줄을 바꾸고 마지막 추가 빈 줄을 제거해야 합니다.

UNIX: 파일의 마지막 줄을 바꾸고 마지막 추가 빈 줄을 제거해야 합니다.

파일 끝의 -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": 텍스트가 추가됩니다.

관련 정보