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":テキストが追加されます。

関連情報