在python中每20分钟编辑一个文件中的特定单词

在python中每20分钟编辑一个文件中的特定单词

问题描述:

我想在下面的文件中以特定间隔(例如每30分钟)更改omega的值。该文件在运行时由另一个程序使用。我想慢慢地从0-10斜坡RPM值(线上的最后一个入口)。基本上,下面的文件中的值“5”需要以每30分钟1次的增量从0-10变化。在python中每20分钟编辑一个文件中的特定单词

rotor 
{ 
    // Fixed patches (by default they 'move' with the MRF zone) 
    nonRotatingPatches(); //if something blows up ..fill the non rotating patches between "(baffles, pressureOutlet etc)" 

    origin origin [0 1 0 0 0 0 0] (0 0 0); 
    axis  axis [0 0 0 0 0 0 0] (0 0 1); 
    omega omega [0 0 -1 0 0 0 0] 5; 
} 

我曾尝试下面的代码(我不知道该怎么办的,每30分钟部分),而是由file.writelines(data)方法写入的数据似乎并没有纳入我作出值的变化。

import os 
import sys 
import fileinput 

with open('MRFzones', 'r') as file: 
    data = file.readlines() 

# The line omega is line 27 in the file. 
line = data[26] 
word = line.split() 

# >>> data[26].split() 
# ['omega', 'omega', '[0', '0', '-1', '0', '0', '0', '0]', '5;'] 
# The part i want to change is the 10th word. 
word[9] = '10;' 

# Write everything back. 
with open('MRFzones', 'w') as file: 
    file.writelines(data) 

这是行不通的 - 在更新的文件中5未被更改为10。有人可以帮我实施吗?我可能甚至没有正确的想法,所以我们可以在必要时从头开始编写代码。

感谢, 苏雷什

你是不是修改data在所有 - 你提取lineword和修改的。最后,您将原始文件data写回文件。

我不会使用Python这一点,而是一个shell脚本(前提是你在一个类Unix操作系统):

for i in 0 1 2 3 4 5 6 7 8 9 10; do 
    sleep 30 
    sed -i "26s/[0-9]+;/$i/" MRFzones 
od 
+0

THA nks的响应..我正在学习Python,并试图使用该程序做一些自动化!是的,我在unix中使用了类似的脚本来做同样的事情。你的要简单得多,但是一般情况下应该使用python!? -suresh – Suresh 2011-05-02 08:30:59

+0

@user:我明白了,如果你的目标是学习Python而不是完成任务:)我的答案并不是非常有用:) – 2011-05-02 08:33:41

+0

就像我说的那样..工作正在完成,但我也想知道如果我不得不使用Python,我将如何去呢? – Suresh 2011-05-02 08:39:03

您可以通过fileinput模块识别您的线路及其组件您导入和正则表达式的re模块:

>>> import re 
>>> pattern = r'(\s*omega\s+omega\s+\[-?\d+ -?\d+ -?\d+ -?\d+ -?\d+ -?\d+ -?\d+\]) (-?\d+);' 

花括号是用来捕捉模式,看看在re module了解更多(非常有用的Python模块,非常出色地完成和记录)!

我们有我们的模式,现在在我们的文件就地浏览:print用于直接在文件中写入(不再打印到屏幕),当for循环结束(文件关闭)时标准功能恢复正常。

不要忘记删除换行符以避免在输出文件中出现不需要的换行符(是的,这有点烦人:循环给出的line变量包含换行符\n)!

>>> from fileinput import FileInput 
>>> path = 'D:\\Temp\\Toto.txt' 
>>> for line in FileInput(path, inplace=1): 
     line = line.replace('\n', '') 
     match = re.match(pattern, line) 
     if match: 
      line = '{0} {1};'.format(match.groups()[0], '145') 
      print line 
     else: 
      print line 

现在,您可以浏览您的旧文件,该值5145取代。 我个人不同意斯文,Python对我来说是处理这种情况的完美语言。

+0

+1对'inplace = 1'。代码可以改进,但(见我的答案)。 – EOL 2011-05-02 10:00:22

做你想做的事情的规范方式确实是使用正则表达式模块(re)。它可以直接在“欧米茄”线进行更换:

import re 

for count in range(10): 

    # Reading: 
    with open('MRFzones') as input_file: # Automatically closes the file after reading 
     contents = input_file.read() # Whole file 

    # Writing: 
    with open('MRFzones', 'w') as out_file: 
     # The 'omega.*(\d+)' searches for a line with "omega" followed at some point by digits and ";". sub() performs 
     # a substitution of the part matched inside the parentheses: 
     out_file.write(re.sub('omega +(\d+);', str(count), contents, count=1)) # count=1 only modifies the first omega line 
+0

必须有'?'在''''*'之后'(\ d +);''',否则''(\ d +)'只会匹配最后一个数字的最后一位,也就是'1'数字将是'10'。顺便说一句,我不明白为什么它应该是'''。*?'''而不是''+''',因为在所需的数字之前没有其他空格。 – eyquem 2011-05-02 15:03:37

+0

@eyquem:谢谢。我想我最初的意思是'*'(而不是''*')。 – EOL 2011-05-09 19:27:14

使用Python,你可以在一个文件中使用正则表达式和处理与模式“RB +”:

import re 
from time import sleep 

regx = re.compile('^ +omega +omega +\[[ \d.eE+-]+\] +(\d\d?)(;.+)',re.MULTILINE|re.DOTALL) 

for i in xrange(1,11): 
    sleep(20*60) 
    with open('MRFzones', 'rb+') as f: 
     m = regx.search(f.read()) 
     x = m.start(1) 
     f.seek(x,0) 
     f.writelines((str(i),m.group(2))) 
     f.tuncate() 

我假设初始文件是包含

'  omega omega [0 0 -1 0 0 0 0] 0;' 

是记录匹配 在这些结果的结果MatchObject,叔这里有:

  • 在文件的内容中的位置,其中开始由所述第一组中的匹配擦肩而过,1或2位(一个或多个)序列中,一个由(\d\d?)定义。该开始经由方法获得开始()的称为用1作为参数
  • 由第二组中的匹配钓到的文本中,(;.+)定义,由方法得到组()的称为用2作为参数

re.MULTILINE使得在正则表达式匹配线的每个开始的图案符号“^”,即每个'\n'后和在第精确字符串的开头。如果没有re.MULTILINE“^”意味着只能与字符串

re.DOTALL开头的匹配,使点的模式匹配任何字符,包括新行。所以';.+'的意思是:字符';'以及后面的所有字符';'直到字符串的最后。如果没有re.DOTALL,模式中的符号点将停止匹配该行的末尾。

执行f.read()后,文件的指针位于硬盘驱动器上文件的末尾。 seek()允许移动它。在这种情况下,seek(x,0)将指针移到一个位置,该位置位于从文件开头起的x个字符(0表示'从开始',请参阅seek()以了解其他类型的移动)

执行f.seek(x,0)之后,指针位于要更改的整数之前。写作str(i)删除和写在古代号码。

f.truncate()是使文件在当前位置结束。在我的代码中,它并不是绝对必需的,因为被替换的字符串总是被长度相同或更长的字符串替换。

注意,此代码可以如果存在对于其中可以写入两个字符的文件中的数保留的两个位置被简化:“0”,“1”,“2”,“3”,等

在这种情况下,代码可以是:

​​

import re 
from time import sleep 

regx = re.compile('^ +omega +omega +\[[ \d.eE+-]+\] +(\d\d?)(;.+)',re.MULTILINE|re.DOTALL) 

with open('Copie de oso.txt', 'rb+') as f: 
    m = regx.search(f.read()) 
    x = m.start(1) 
    f.seek(x,0) 
    f.writelines((' 1',m.group(2))) 
    f.truncate() 

for i in xrange(2,11): 
    sleep(20) 
    with open('Copie de oso.txt', 'rb+') as f: 
     f.seek(x,0) 
     f.write('{:>2}'.format(i)) 

PS

括号'['']' 中的图案的符号序列[ \d.eE+-]定义一组字符。我在这两个括号之间放置了所有可能用于编写数字的字符。重要的是,' - '将在该集合的末尾,否则这将意味着另一个事物,即只是' - '字符。

'\[''\]'和是转义括号来表示只是字符“括号”,而不是限定的一组

我选用赶上符号括号“[0 0 -1 0 0 0 0]”与万一图案,该号码可以是任何其它种类的数目的部分\[[ \d.eE+-]+\],在任何类型的表示的(由指数表示法)表示

' +'在图案的意思是“任意数量的毛坯”