簡體   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