'20/08/13更新:見づらかったので記事構成を編集しました。
本コードの仕様について説明します。下図左にある「@TARGET_*@」のように@で囲まれた複数箇所を下図右のように置換する雛形コードを載せました。複数行に渡って置換している元データは、別ファイルからpandasを用いて抽出後、加工して置換します。

具体例を示します。下図4つのファイルを作成します。

▼ファイル①「abc.txt」
置換対象のファイルです。@で囲まれた箇所を置換します。
aaa
hhhhhhhhhhhhhhhhhh
22222222
@TARGET_2@
@TARGET_3@
@TARGET_1@
end
▼ファイル②「dataA.csv」
置換するデータです。ここから指定データをpandasで抽出します。
No,Property,Material
1,IS1,Cu
2,GF1_2,Ag
3,NT1_2,Au
4,GF1_3,Ag
5,GF1_1,Ag
6,NT1_1,Au
7,GF1_5,Ag
8,GF1_4,Ag
9,NT1_4,Au
10,IS2,Cu
11,GF2_2,Ag
12,NT2_2,Au
13,GF2_3,Ag
14,NT2_3,Au
15,GF2_1,Ag
16,NT2_1,Au
17,GF2_5,Ag
18,NT2_5,Au
19,GF2_4,Ag
20,NT2_4,Au
21,IS3,Cu
▼ファイル③「dataB.csv」
置換するデータです。ここから指定データをpandasで抽出します。
name,x_min,x_max,y_min,y_max,z_min,z_max
A1,0,0.3,0.15,0.15,-0.1,0.1
A2,0,0.3,0.15,0.15,0.2,0.4
A3,0,0.3,0.15,0.15,0.5,0.7
B1,0,0.3,-0.15,-0.15,-0.1,0.1
B2,0,0.3,-0.15,-0.15,0.2,0.4
B3,0,0.3,-0.15,-0.15,0.5,0.7
▼ファイル④「replace.py」
本体プログラムです。例えば、コマンドプロンプトでカレントディレクトリへ移動して「python replace.py」と実行すれば、冒頭の図のように置換した結果ファイルを得られます。
■本プログラム
import os, sys, shutil
import pandas as pd
def myComment():
buf=[]
buf.append('fruits' + '\n')
buf.append(' orange' + '\n')
buf.append(' apple' + '\n')
buf.append(' grape' + '\n')
return buf
class Extract_dataA:
def __init__(self, data_file):
self.df = pd.read_csv(data_file, header=0)
print('self.df -> ' + str(self.df))
def select_columndata(self, select_column, extract_name):
select_df = self.df[self.df[select_column]==extract_name]
return select_df
def sort_columndata(self, DF, sort_column):
sort_df = DF.sort_values(sort_column, ascending=True)
return sort_df
def extra_columndata(self, DF, extract_name, extract_column):
columnlist = DF[extract_column].values.tolist()
print('columnlist -> ' + str(columnlist))
buf=[]
buf.append('dataset '+ str(dict[extract_name]) + '=[')
for i in range(len(columnlist)):
if (i < len(columnlist)-1):
buf.append('\"' + extract_column + str(columnlist[i])+'\",')
else:
buf.append('\"' + extract_column + str(columnlist[i])+'\"')
buf.append(']' + '\n')
return buf
class Extract_dataB:
def __init__(self, data_file):
self.df = pd.read_csv(data_file, header=0, index_col=0)
print('self.df -> ' + str(self.df))
self.indexlist = self.df.index.values.tolist()
print(self.indexlist)
def data_set(self):
buf=[]
for i in range(len(self.indexlist)):
tmplist=[]
tmplist=self.df.loc[str(self.indexlist[i])].values.tolist()
buf.append('func(name=' +str(self.indexlist[i]) + ',\n')
buf.append(' x_min='+str(tmplist[0])+ ', x_max=' +str(tmplist[1])+ ',\n')
buf.append(' y_min='+str(tmplist[2])+ ', y_max=' +str(tmplist[3])+ ',\n')
buf.append(' z_min='+str(tmplist[4])+ ', z_max=' +str(tmplist[5])+ ')\n')
return buf
def create_file(replace_set, replace_list):
tmp_list=[]
flag=0
with open(replace_set[0], "r") as f1:
k=0
for row in f1:
if row.find(replace_set[2]) != -1:
flag = k
print('flag -> ' + str(flag))
tmp_list.append(replace_list)
print(tmp_list[flag])
else:
tmp_list.append(row)
k=k+1
if replace_set[0]==replace_set[1]:
os.remove(replace_set[0])
with open(replace_set[1], "w") as f2:
for i in range(len(tmp_list)):
if i != flag:
f2.write(str(tmp_list[i]))
else:
f2.writelines(tmp_list[i])
if __name__ == "__main__":
replace_set1 = ('abc.txt', 'abc2.txt', '@TARGET_1@')
replace_set2 = ('abc2.txt', 'abc3.txt', '@TARGET_2@')
replace_set3 = ('abc3.txt', 'abc4.txt', '@TARGET_3@')
replace_list1 = myComment()
replace_list2 = []
data_file = 'dataA.csv'
select_column = 'Material'
extract_name = ['Au','Ag','Cu']
dict={"Au":'gold', "Ag":'silver', "Cu":'bronze'}
extract_column = 'No'
sort_column = 'Property'
for i in range(len(extract_name)):
myInstanceA = Extract_dataA(data_file)
mydf1 = myInstanceA.select_columndata(select_column, extract_name[i])
print(mydf1)
mydf2 = myInstanceA.sort_columndata(mydf1, sort_column)
print(mydf2)
mylist = myInstanceA.extra_columndata(mydf2, extract_name[i], extract_column)
print(mylist)
replace_list2.extend(mylist)
print('replace_list2-----------------')
print(replace_list2)
data_file = 'dataB.csv'
myInstanceB = Extract_dataB(data_file)
replace_list3 = myInstanceB.data_set()
create_file(replace_set1, replace_list1)
create_file(replace_set2, replace_list2)
create_file(replace_set3, replace_list3)
本コードに関する特記事項は下記二つです。
1. 置換するためのデータファイルを読み込むために、クラスを二つ用意した。
インデックス(行名)がないcsvファイル等を読み込む用にはクラス「Extract_dataA」。一方のクラス「Extract_dataB」はインデックスを一番左列に指定してcsv等のファイルを読み込む用です。それぞれ、その下に関数(クラスなのでメソッド)を作成していく仕様で、汎用性を考慮したためです。
2. 置換元と置換後のファイル名をinputfile, outputfileで指定できる。
もし、両者を同名で指定すれば、ファイル自体も置換した結果になります。例えば、本コード中の「abc2.txt」「abc3.txt」「abc4.txt」を「abc.txt」にすれば可能です。
以上
<広告>
リンク