这可能是一项简单的任务,但目前我真的不知道如何以简单的方式做到这一点。 我有以下情况,我有一个用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?
我试图在脚本中执行此操作,但如果我使用选项卡而不是位置之间的多个空格,脚本将失败。 我搜索了很多,但找不到任何好的解决方案。 我熟悉C ++和一些小批量脚本,但即使我必须学习另一种语言的基础知识,我也很满意每一种解决方案。
我试图在C ++中找到一种方法,但我想出的方法可能无法格式化n行,而每一行都是复杂的。帧数/行数每次都不同,所以我从来没有固定的行数。
答案 0 :(得分:2)
这样的事可能有用。我没有对数字进行任何特殊格式化,因此如果您需要,您需要添加它。如果您担心输入文件格式不正确,例如一行中的数字不够,那么您需要添加一些额外的错误检查以防范它。
#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" << 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;
}
答案 1 :(得分:2)
使用正则表达式的另一个例子
#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;
}
答案 2 :(得分:1)
感兴趣的示例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")