将文本替换为前置字符串和后置字符串

发布于 2024-12-10 17:53:23 字数 630 浏览 0 评论 0原文

我有一个文件,其中有一些具有公共字符串的行:

_report_file <<

所以上面的文本可以是任何东西,但它以分号(;)结尾 例如,请参见下面的行:

CACUP_updater::_report_file << "The job has terminated." << endl;

该行的另一个示例可以是:

_report_file << "The job is reading." << endl;

我需要将 abc; 作为前置字符串附加,将 xyz; 作为后置字符串附加到该行,以便该行看起来

abc;CACUP_updater::_report_file << "The job has terminated." << endl;xyz;

基本上我想搜索 "_report_file <<",选择完整的行并在前后添加一些文本。 我怎样才能在 sed 或 perl 或 awk 中做到这一点。

I have file in which there are certian lines which have common string:

_report_file <<

SO the text around this above can be any thingbut it ends with semiclon(;)
for eg see the line below:

CACUP_updater::_report_file << "The job has terminated." << endl;

another example of the line can be:

_report_file << "The job is reading." << endl;

i need to append abc; as pre string and xyz; as post string to that line so that the line looks like

abc;CACUP_updater::_report_file << "The job has terminated." << endl;xyz;

basically i want to search for "_report_file <<",select the complete line and pre and post append some text.
how can i do this in sed or perl or awk.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

马蹄踏│碎落叶 2024-12-17 17:53:23

Perl 方式:

perl -anE 'chomp;s/^(.*?::_report_file <<.*;)$/abc;$1xyz;/;say;' foo.txt > foo2.txt

perl -ane 'chomp;s/^(.*?::_report_file <<.*;)$/abc;${1}xyz;/;print "$_\n";' foo.txt > foo2.txt

A perl way:

perl -anE 'chomp;s/^(.*?::_report_file <<.*;)$/abc;$1xyz;/;say;' foo.txt > foo2.txt

or

perl -ane 'chomp;s/^(.*?::_report_file <<.*;)$/abc;${1}xyz;/;print "$_\n";' foo.txt > foo2.txt
挽梦忆笙歌 2024-12-17 17:53:23
$ perl -i.bak -n -e 'print "abc;${_}xyz;"' your_file_here

这也会为您提供该文件的备份副本。

$ perl -i.bak -n -e 'print "abc;${_}xyz;"' your_file_here

That'll give you a backup copy of the file too.

想念有你 2024-12-17 17:53:23
awk '/_report_file <</{$0="abc;" $0 "xyz;"}{print}'
awk '/_report_file <</{$0="abc;" $0 "xyz;"}{print}'
默嘫て 2024-12-17 17:53:23
perl -pi.bak -e 's{.*_report_file <<.*}{abc;
amp;xyz;}' file_name_here
perl -pi.bak -e 's{.*_report_file <<.*}{abc;
amp;xyz;}' file_name_here
只有影子陪我不离不弃 2024-12-17 17:53:23

编辑以回复您更新的问题。我认为你做错了:)

我建议你这样做:

#!/usr/bin/perl
use strict;
use warnings;

while(<>)
{
    s/([\w]+::)?_report_file\s*<<\s*(.*);/CACUP_REPORT($2);/go;
    print
}

这样,你可以在 C++ 中定义一个像

#define CACUP_REPORT(message) do { \
    /* abc; */ \
    ::CACUP_updater::_report_file << message; \
    /* xyz; */ } while (false)

But Why? 这样的

  • 宏。

    您可以在其他地方阅读有关安全宏的所有内容1

  • 您将获得更大的灵活性。您稍后可以一次性更改所有实例。

  • 您可以委托给一个函数

  • 您可以声明一个临时stringstream并将结果文本写入整个其他介质(网络?fwrite?内存缓冲区?两个流?)。

  • 您可以根据全局 falg 进行有条件的日志记录,而不必通过代码重复对其进行检查。

好吧,你明白了:它几乎是DRY原理

示例输入:

#include <iostream>
using namespace std;

namespace CACUP_updater
{
    std::ostream& _report_file = std::cout;

    void start_reading()
    {
        _report_file << "The job is reading." << endl;
    }
}

int main()
{
    CACUP_updater::_report_file << "The job is starting." << endl;
    CACUP_updater::start_reading();
    CACUP_updater::_report_file << "The job has terminated." << endl;
}

示例输出:

例如 perl -i.bck test.cpp 的结果是 2

#include <iostream>
using namespace std;

namespace CACUP_updater
{
    std::ostream& _report_file = std::cout;

    void start_reading()
    {
        CACUP_REPORT("The job is reading." << endl);
    }
}

int main()
{
    CACUP_REPORT("The job is starting." << endl);
    CACUP_updater::start_reading();
    CACUP_REPORT("The job has terminated." << endl);
}

宏实现的一些想法:

这展示了如何

  • 使用临时流将
  • print 字符串化到多个输出流,有条件地
  • 正确处理异常,内联
  • 添加日期时间戳(仅用于写入日志文件,而不是 stderr)
  • 当然,有足够的空间容纳任何abc;xyz; 您的想法:)

#include <iostream>
#include <sstream>
#include <fstream>

using namespace std;

static bool _verbose = false;

#define CACUP_REPORT(message) do { \
    std::stringstream ss; \
    ss << message; \
    ::CACUP_updater::log_helper(ss.str()); \
    } while (false)

namespace CACUP_updater
{
    std::string getdatetime() { return "YYYY/MM/DD - HH:MM:SS.mmm"; } // demo only
    void log_helper(const std::string& msg)
    {
        try
        {
            std::ofstream ofs("/tmp/myprogram.log", std::ios_base::app);

            ofs << getdatetime() << "\t" << msg;
            ofs.flush();
            ofs.close();

            // log errors always to stderr, 
            // and all other messages if verbose is set
            if (_verbose || std::string::npos != msg.find("ERROR"))
                std::cerr << msg << std::endl;
        } catch(std::exception& e)
        {
            std::cerr << "Unhandled error writing to log: '" << e.what() << std::endl;
        }
    }

    void start_reading()
    {
        CACUP_REPORT("The job is reading." << endl);
    }
}

int main()
{
    CACUP_REPORT("The job is starting." << endl);
    CACUP_updater::start_reading();
    CACUP_REPORT("The job has terminated." << endl);
}

文件的输出为:

YYYY/MM/DD - HH:MM:SS.mmm   The job is starting.
YYYY/MM/DD - HH:MM:SS.mmm   The job is reading.
YYYY/MM/DD - HH:MM:SS.mmm   The job has terminated.

stderr 的输出取决于 verbose 标志



1 想象一下如果 if (b) _report_file << 会发生什么“好的!” << std::endl; ?

2 请注意,创建了一个备份文件:test.cpp.bck

Edit in response to your updated question. I think you're doing it wrong :)

I suggest you do it this way instead:

#!/usr/bin/perl
use strict;
use warnings;

while(<>)
{
    s/([\w]+::)?_report_file\s*<<\s*(.*);/CACUP_REPORT($2);/go;
    print
}

That way, you can, in C++, define a macro like

#define CACUP_REPORT(message) do { \
    /* abc; */ \
    ::CACUP_updater::_report_file << message; \
    /* xyz; */ } while (false)

But Why?

  • You can read all about safe macros elsewhere 1.

  • You get way more flexibility. You can later change all instances at one point.

  • You can delegate to a a function

  • You could declare a temporary stringstream and write the resulting text to a whole other medium (network? fwrite? memory buffer? two streams?).

  • You could make the logging conditional depending on a global falg without having to duplicate the check for it throughour your code.

Well you get it: it pretty much the DRY principle.

Sample input:

#include <iostream>
using namespace std;

namespace CACUP_updater
{
    std::ostream& _report_file = std::cout;

    void start_reading()
    {
        _report_file << "The job is reading." << endl;
    }
}

int main()
{
    CACUP_updater::_report_file << "The job is starting." << endl;
    CACUP_updater::start_reading();
    CACUP_updater::_report_file << "The job has terminated." << endl;
}

Sample output:

The result of, e.g. perl -i.bck test.cpp is 2:

#include <iostream>
using namespace std;

namespace CACUP_updater
{
    std::ostream& _report_file = std::cout;

    void start_reading()
    {
        CACUP_REPORT("The job is reading." << endl);
    }
}

int main()
{
    CACUP_REPORT("The job is starting." << endl);
    CACUP_updater::start_reading();
    CACUP_REPORT("The job has terminated." << endl);
}

Some ideas for implementations of the macro:

This shows how you can

  • use a temporary stream to stringify
  • print to more than one output stream, conditionally
  • handle exceptions properly inline
  • add a datetime stamp (only for writing to the log file, not stderr)
  • of course, there is more than enough room to accomodate any abc; or xyz; you had in mind :)

.

#include <iostream>
#include <sstream>
#include <fstream>

using namespace std;

static bool _verbose = false;

#define CACUP_REPORT(message) do { \
    std::stringstream ss; \
    ss << message; \
    ::CACUP_updater::log_helper(ss.str()); \
    } while (false)

namespace CACUP_updater
{
    std::string getdatetime() { return "YYYY/MM/DD - HH:MM:SS.mmm"; } // demo only
    void log_helper(const std::string& msg)
    {
        try
        {
            std::ofstream ofs("/tmp/myprogram.log", std::ios_base::app);

            ofs << getdatetime() << "\t" << msg;
            ofs.flush();
            ofs.close();

            // log errors always to stderr, 
            // and all other messages if verbose is set
            if (_verbose || std::string::npos != msg.find("ERROR"))
                std::cerr << msg << std::endl;
        } catch(std::exception& e)
        {
            std::cerr << "Unhandled error writing to log: '" << e.what() << std::endl;
        }
    }

    void start_reading()
    {
        CACUP_REPORT("The job is reading." << endl);
    }
}

int main()
{
    CACUP_REPORT("The job is starting." << endl);
    CACUP_updater::start_reading();
    CACUP_REPORT("The job has terminated." << endl);
}

The output to the file is:

YYYY/MM/DD - HH:MM:SS.mmm   The job is starting.
YYYY/MM/DD - HH:MM:SS.mmm   The job is reading.
YYYY/MM/DD - HH:MM:SS.mmm   The job has terminated.

The output to the stderr depends on the verbose flag



1 just imagine what would happen if if (b) _report_file << "ok!" << std::endl; ?

2 note that a backup file is created: test.cpp.bck

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文