繁体   English   中英

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

[英]Editing a SPECIFIC word in a file in python, every 20 mins

我想以特定的时间间隔更改下面文件中 omega 的值,比如每 30 分钟一次。 该文件在运行时被另一个程序使用。 我想缓慢地将 RPM 值(行中的最后一个条目)从 0 增加到 10。 本质上,下面文件中的值“5”需要以每 30 分钟 1 的增量从 0-10 变化。

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

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

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

大括号用于捕获模式,请查看re 模块以了解更多信息(非常有用的 Python 模块,做得很好并记录在案)!

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

不要忘记删除换行符以避免 output 文件中出现不需要的换行符(是的,这有点烦人:循环给出的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

您现在可以浏览旧文件,值5已替换为145 我个人不同意 Sven 的观点,Python 对我来说是处理这种情况的完美语言。

做你想做的事的规范方法确实是使用正则表达式模块( re )。 它可以直接在“omega”行中执行替换:

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

使用 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;'

m是记录匹配结果的MatchObject,这些结果中,有:

  • 文件内容中的 position 开始由匹配中的第一组捕获的 1 或 2 位序列,该组由(\d\d?)定义。 这个开始是通过以 1 作为参数调用的m的方法start()获得的
  • 匹配中第二组捕获的文本,由(;.+)定义,由m的方法group()获得,以 2 作为参数调用

re.MULTILINE使正则表达式模式中的符号'^'与每个行首匹配,即恰好在每个'\n'之后和字符串的开头。 如果没有re.MULTILINE'^'仅表示与字符串开头的匹配

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

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

执行f.seek(x,0)后,指针就在您要更改的 integer 之前。 写入str(i)擦除并写入古代数字。

f.truncate()是使文件以当前 position 结尾。 就我的代码而言,这不是绝对必要的,因为被替换的字符串总是被相同或更长长度的字符串替换。

.

请注意,如果在文件中为可以写入两个字符的数字保留两个位置,则可以简化此代码:'0'、'1'、'2'、'3'等

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

import re
from time import sleep

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

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.write('{:>2}'.format(i))

或者

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))

.

附言

模式中符号序列[ \d.eE+-]的括号'['']'定义了一组字符。 我把所有可能用来写数字的字符放在这两个括号之间。 重要的是, '-'位于集合的末尾,否则它意味着另一个东西,只是'-'字符。

'\[''\]'是转义括号,仅表示字符“括号”,而不是定义集合的符号括号

我选择用模式的\[[ \d.eE+-]+\]部分来捕捉'[0 0 -1 0 0 0 0]'以防数字可能是任何其他类型的数字,以任何形式表示表示形式(包括指数符号)

模式中的' +'表示“任意数量的空格”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM