这可能是一个简单的任务,但目前我真的不知道如何以一种简单的方式做到这一点。 我有以下情况,我有一个脚本写在COFFEE,3D程序Cinema 4D的脚本语言。 现在这个脚本将以下格式的位置数据写入文本文件(在这种情况下是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?
我试图在脚本中这样做,但脚本失败,如果我使用一个选项卡,而不是我的立场之间的几个空格。 我search了很多,但找不到任何好的解决scheme。 我熟悉C ++和一些批处理脚本,但是即使我需要学习其他语言的基础知识,我也很乐意为每个解决scheme。
我试图用C ++find一种方法,但是我没有办法可以格式化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 << "Transform\tPosition\n\tFrame\tX pixels\tY pixels\tZ pixels" << std::endl; for(PositionVec::iterator it = Positions.begin(); it != Positions.end(); ++it) { const PositionData& p(*it); OutFile << "\t" << p.FrameNum << "\t" << pX << "\t" << pY << "\t" << pZ << 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; }
又一个使用正则表达式的例子
#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 << "Transform\tPosition" << endl; cout << "\tFrame\tX pixels\tY pixels\tZ 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 = "Transform\tPosition\n" column_str = "\tFrame\tX pixels\tY pixels\tZ pixels\n" closer_str = "End of Keyframe Data\n" # 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")