UNIX: Precisa substituir a última linha no arquivo e também remover a linha extra em branco no final

1

Eu preciso substituir - WOR para VWOR no final do arquivo.

Eu tentei

sed s/WOR/VWOR/g    

Mas isso não funciona até que eu tenha uma nova linha em branco no arquivo.

Então eu usei

( cat FileName && echo ) | sed 's/WOR/VWOR/g'  

Isso funcionou. Mas está demorando muito para ser substituído, pois o sed está lendo o arquivo inteiro.

    
por Dan13 11.11.2016 / 14:30

2 respostas

2

Verifique se o arquivo termina em uma nova linha. Isso é um requisito de "arquivos de texto".

Este comando fará exatamente isso :

[ -n $(tail -c1 FileName) ] && printf '\n' >> FileName

Ele adicionará uma nova linha à direita apenas se for necessário, então não há problema se for usado várias vezes, também, é muito rápido, pois só verifica o último caractere.

Em seguida, faça a alteração na última linha (agora válida) ($):

sed -ie '$s/WOR/VWOR/'

Nota: Este comando irá converter um symlink em um arquivo real.

    
por 11.11.2016 / 23:15
0

Bem, eu não sei como resolver isso com sed / awk ou outro. Aqui está em C e deve ser bem rápido:

/*
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;
}
    
por 12.11.2016 / 09:49