用pre和post字符串替换文本

时间:2011-10-20 14:19:06

标签: perl unix sed awk

我的文件中有certian行有共同的字符串:

_report_file <<

所以围绕上面的文字可以是任何东西,但它以semiclon(;)结尾 例如,见下面的一行:

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中这样做。

5 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

我建议你这样做:

#!/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)

但为什么?

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

  • 您获得更多灵活性。您可以稍后在一个点更改所有实例。

  • 您可以委派一个功能

  • 您可以声明一个临时的stringstream并将结果文本写入另一个媒体(网络?fwrite?内存缓冲区?两个流?)。

  • 您可以根据全局falg使日志记录具有条件,而无需通过代码复制检查。

嗯,你得到它:它几乎是 DRY principle

样本输入:

#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);
}

实现宏的一些想法:

这显示了你如何

  • 使用临时流进行字符串化
  • 有条件地打印到多个输出流
  • 正确处理内联异常
  • 添加日期时间戳(仅用于写入日志文件,而不是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 << "ok!" << std::endl;

会发生什么

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

答案 2 :(得分:0)

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

那也会给你一份文件的备份副本。

答案 3 :(得分:0)

awk '/_report_file <</{$0="abc;" $0 "xyz;"}{print}'

答案 4 :(得分:0)

perl -pi.bak -e 's{.*_report_file <<.*}{abc;$&xyz;}' file_name_here