2

У меня есть этот файл конфигурации, который я хочу редактировать программно. Я всегда использую sed для небольших изменений, но теперь мне нужно заменить 1 строку для нескольких строк, примерно так:

some code
# maintenance placeholder
more code

Измени это на это

some code
maintenance line 1
maintenance line 2
maintenance line 2
more code

Как я могу это сделать?

3 ответа3

2

Если у вас есть Perl, попробуйте использовать:

perl -pi.bak -e 's/oldtext/newtext/' file.txt

это заменит 'oldtext' на 'newtext' в file.txt и создаст резервную копию файла с именем file.txt.bak

2

Я продолжил и создал для вас небольшую утилиту на C++, надеюсь, она вам пригодится. Просто скомпилируйте и наслаждайтесь.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc,char *argv[])
{
    fstream i,
                    s,
                    r,
                    o;
    string s_str,
                 r_str,
                 buf;
    int n;
    char ch,
             s_in = 1,
             s_out = 1;

    for(int n = 1; n < argc; n += 2)
    {
        if(argv[n][0] == '-')
        {
            switch(argv[n][1])
            {
                case 'i':
                    i.open(argv[n+1], fstream::in);
                    s_in = 0;
                    break;
                case 's':
                    s.open(argv[n+1], fstream::in);
                    break;
                case 'r':
                    r.open(argv[n+1], fstream::in);
                    break;
                case 'o':
                    o.open(argv[n+1], fstream::out);
                    s_out = 0;
                    break;
                default:
                    cerr << "Usage: helper [-i input_file] <-s search_file> <-r replace_file> [-o output_file]";
                    return 0;
            }
        }
    }
    if(!s_in && !i.is_open())
    {
        cerr << "Input could not be opened.";
        return -1;
    }
    if(!s.is_open())
    {
        cerr << "Search could not be opened.";
        return -1;  
    }
    if(!r.is_open())
    {
        cerr << "Replace could not be opened.";
        return -1;
    }
    if(!s_out && !o.is_open())
    {
        cerr << "Output could not be opened.";
        return -1;
    }

    /* get s and r in memory */
    while((ch = s.get()) != EOF)
        s_str += ch;
    s.close();
    while((ch = r.get()) != EOF)
        r_str += ch;
    r.close();

    buf = "";
    while((s_in ? (ch = cin.get()) : (ch = i.get())) != EOF)
    {
        buf += ch;
        for(n = 0; n < buf.length(); n++)
            if(buf.at(n) != s_str.at(n))
            {
                s_out ? (cout << buf) : (o << buf);
                buf = "";
                break;
            }
        if(n == s_str.length())
        {
            s_out ? (cout << r_str) : (o << r_str);
            buf = "";
        }
    }
    s_out ? (cout << buf) : (o << buf);

    if(!s_in)
        i.close();
    if(!s_out)
        o.close();

    return 0;
}

Составлено с:

g++ -o replacer replacer.cpp

Пример использования:

input.txt:

1
2
3
4
5

search.txt

3

replace.txt

Three

команда

./replacer -i input.txt -s search.txt -r replace.txt -o output.txt

output.txt

1
2
Three
4
5

Если у вас есть еще вопросы, пожалуйста, задавайте. Я надеюсь, что это выполнит то, что вы хотели. (Он также принимает stdin и выводит в stdout, если вы опускаете -i и -o) Конечно, новые строки, кавычки, т.д. Не вызовут проблем, потому что они находятся в отдельных файлах.

1

В случае, если ответ @ u8sand (комментарий) не достаточно ясен для вас, вы можете сделать то, что вы описываете

sed '/# maintenance placeholder/c\
maintenance line 1\
maintenance line 2\
'

Вы можете сделать то же самое в командах s :

sed 's/SuperUser/Super\
User/'

Возможно, как предполагает u8sand, существуют версии sed которых обратный слеш не требуется.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .