使用C++或任何windows脚本语言格式化文本数据

Formatting text data with C++ or any windows scripting language

本文关键字:语言 格式化 文本 数据 脚本 windows C++ 任何 使用      更新时间:2023-10-16

这可能是一项简单的任务,但目前我真的不知道如何用简单的方式做到这一点。我有以下情况,我有一个用COFFEE写的脚本,这是3D程序Cinema4D的脚本语言。现在,这个脚本正在将以下格式的位置数据写入一个文本文件(在这种情况下是rtf,但也可以是.txt)。

0  0.0  471.2  0.0
1  0.0  470.5  0.0
2  0.0  468.8  0.0
3  0.0  465.9  0.0
4  0.0  461.9  0.0
5  0.0  456.8  0.0
6  0.0  450.5  0.0
7  0.0  443.2  0.0
8  0.0  434.8  0.0
9  0.0  425.2  0.0

帧,X,Y,Z。

现在我需要做的是将这个位置数据转换成以下格式:

Transform   Position
    Frame   X pixels    Y pixels    Z pixels    
    0   0.0    471.2    0.0 
    1   0.0    470.5    0.0 
    2   0.0    468.8    0.0 

End of Keyframe Data

它在这里并不真正可见,但这里没有空格,所有东西都用制表符隔开(也许可以复制到记事本上,以真正看到制表符)。重要的是,我在每个数字之间都有制表符,可以有空格,但我每次只需要一个制表符。因此,最重要的部分是,我如何从第一个数据集中获得这些数字,并让程序在每个数字之间添加一个\t?

我试着在脚本中这样做,但如果我在位置之间使用一个选项卡而不是几个空格,脚本就会失败。我找了很多,但找不到任何好的解决方案。我熟悉C++和一个小批量脚本,但我对每一个解决方案都很满意,即使我必须学习另一种语言的基础知识。

我试图在C++中找到一种方法,但我想出的方法无法格式化n行,而且每一行都很复杂。帧/行的数量每次都会变化,所以我从来没有固定的行数。

这样的东西可能会起作用。我没有对数字进行任何特殊的格式化,所以如果你需要,你需要添加它。如果你担心输入文件格式不正确,比如一行上没有足够的数字,那么你会想添加一些额外的错误检查来防止它。

#include <fstream>
#include <iostream>
#include <vector>
bool Convert(const char* InputFilename, const char* OutputFilename)
{
    std::ifstream InFile(InputFilename);
    if(!InFile)
    {
        std::cout << "Could not open  input file '" << InputFilename << "'" << std::endl;
        return false;
    }
    struct PositionData
    {
        double FrameNum;
        double X;
        double Y;
        double Z;
    };
    typedef std::vector<PositionData> PositionVec;
    PositionVec Positions;
    PositionData Pos;
    while(InFile)
    {
        InFile >> Pos.FrameNum >> Pos.X >> Pos.Y >> Pos.Z;
        Positions.push_back(Pos);
    }
    std::ofstream OutFile(OutputFilename);
    if(!OutFile)
    {
        std::cout << "Could not open output file '" << OutputFilename << "'" << std::endl;
        return false;
    }
    OutFile << "TransformtPositionntFrametX pixelstY pixelstZ pixels" << std::endl;
    for(PositionVec::iterator it = Positions.begin(); it != Positions.end(); ++it)
    {
        const PositionData& p(*it);
        OutFile << "t" << p.FrameNum << "t" << p.X << "t" << p.Y << "t" << p.Z << std::endl;
    }
    OutFile << "End of Keyframe Data" << std::endl;
    return true;
}
int main(int argc, char* argv[])
{
    if(argc < 3)
    {
        std::cout << "Usage: convert <input filename> <output filename>" << std::endl;
        return 0;
    }
    bool Success = Convert(argv[1], argv[2]);
    return Success;
}

使用regexps 的另一个示例

#include <fstream>
#include <iostream>
#include <regex>
#include <algorithm>
int main()
{
    using namespace std;
    ifstream inf("TextFile1.txt");
    string data((istreambuf_iterator<char>(inf)), (istreambuf_iterator<char>()));
    regex reg("([\d|.]+)\s+([\d|.]+)\s+([\d|.]+)\s+([\d|.]+)");  
    sregex_iterator beg(data.cbegin(), data.cend(), reg), end;
    cout << "TransformtPosition" << endl;
    cout << "tFrametX pixelstY pixelstZ pixels" << endl;
    for_each(beg, end, [](const smatch& m) {
        std::cout << "t" << m.str(1) << "t" << m.str(2) << "t" << m.str(3) << "t" << m.str(4) << std::endl;
    });
    cout << "End of Keyframe Data" << endl;
}

如果感兴趣,请提供一个Python脚本示例。

#!c:/Python/python.exe -u
# Or point it at your desired Python path
# Or on Unix something like: !/usr/bin/python
# Function to reformat the data as requested.
def reformat_data(input_file, output_file):
    # Define the comment lines you'll write.
    header_str = "TransformtPositionn"
    column_str = "tFrametX pixelstY pixelstZ pixelsn"
    closer_str = "End of Keyframe Datan"
    # Open the file for reading and close after getting lines.
    try:
        infile = open(input_file)
    except IOError:
        print "Invalid input file name..."
        exit()
    lines = infile.readlines()
    infile.close()
    # Open the output for writing. Write data then close.
    try:
        outfile = open(output_file,'w')
    except IOError:
        print "Invalid output file name..."
        exit()
    outfile.write(header_str)
    outfile.write(column_str)
    # Reformat each line to be tab-separated.
    for line in lines:
        line_data = line.split()
        if not (len(line_data) == 4):
            # This skips bad data lines, modify behavior if skipping not desired.
            pass 
        else:
            outfile.write("t".join(line_data)+"n")
    outfile.write(closer_str)
    outfile.close()
#####
# This below gets executed if you call
# python <name_of_this_script>.py
# from the Powershell/Cygwin/other terminal.
#####
if __name__ == "__main__":
    reformat_data("/path/to/input.txt", "/path/to/output.txt")