如何读取文本文件的特定部分(Py 3x)

时间:2019-05-07 17:40:06

标签: python python-3.x

对于Python,其他问题似乎没有得到解决或没有得到解决。我试图让它找到关键字“名称”,将位置设置在那里,然后将变量设置为该特定行,然后让它仅将那段文字用作变量。简而言之,我正在尝试根据将始终存在的“名称”或“ HP”在.txt文件中定位一个变量。

我希望这是有道理的...

我尝试使用currentplace之类的不同变量代替namePlace,但均无效。

import os

def savetest():
    save = open("nametest_text.txt", "r")
    print("Do you have a save?")
    conf = input(": ")
    if conf == "y" or conf == "Y" or conf == "Yes" or conf == "yes":
        text = save.read()
        namePlace = text.find("name")
        currentText = namePlace + 7
        save.seek(namePlace)
        nameLine = save.readline()
        username = nameLine[currentText:len(nameLine)]
        print(username)

        hpPlace = text.find("HP")
        currentText = hpPlace + 5
        save.seek(hpPlace)
        hpLine = save.readline()
        playerHP = hpLine[currentText:len(hpLine)]
        print(playerHP)
        os.system("pause")
        save.close()
savetest()

我的文本文件很简单:

name = Wubzy

HP = 100

我希望它打印出name等号后的所有内容,与HP相同,但不打印nameHP本身。

所以它应该只是打印

Wubzy
100
Press any key to continue . . .

但是它会打印

Wubzy


Press any key to continue . . .

4 个答案:

答案 0 :(得分:0)

使用正则表达式基于模式进行提取:

'(?:name|HP) = (.*)'

这将捕获在等号后加nameHP的所有内容。

代码

import re

with open("nametest_text.txt", "r") as f:    
    for line in f:
        m = re.search(r'(?:name|HP) = (.*)', line.strip())
        if m:
            print(m.group(1))

答案 1 :(得分:0)

最简单的方法可能是使用str.split(),然后在'='字符后打印所有内容:

with open("nametest_text.txt", "r") as f:    
    for line in f:
        if line.strip():
            print(line.strip().split(' = ')[1])

输出:

Wubzy
100

答案 2 :(得分:0)

对于regex来说,这看起来不错。正则表达式可以匹配并捕获文本中的模式,这似乎正是您要尝试的方式。

例如,正则表达式^name\s*=\s*(\w+)$将匹配具有确切文本“名称”的行,后跟0或多个空格字符,“ =”,然后是0或多个空格字符,然后是一个或更多字母。它将在最后捕获单词组。

正则表达式^HP\s*=\s*(\d+)$将匹配具有精确文本“ HP”的行,后跟0或多个空格字符,“ =”,然后是0或多个空格字符,然后是一个或多个数字。它将捕获最后的数字组。


# This is the regex library
import re

# This might be easier to use if you're getting more information in the future.
reg_dict = {
    "name": re.compile(r"^name\s*=\s*(\w+)$"),
    "HP": re.compile(r"^HP\s*=\s*(\d+)$")
}


def savetest():
    save = open("nametest_text.txt", "r")
    print("Do you have a save?")
    conf = input(": ")
    # instead of checking each one individually, you can check if conf is
    # within a much smaller set of valid answers
    if conf.lower() in ["y", "yes"]:
        text = save.read()

        # Find the name
        match = reg_dict["name"].search(text)
        # .search will return the first match of the text, or if there are
        # no occurrences, None
        if(match):
            # With match groups, group(0) is the entire match, group(1) is
            # What was captured in the first set of parenthesis
            username = match.group(1)
        else:
            print("The text file does not contain a username.")
            return
        print(username)

        # Find the HP
        match = reg_dict["HP"].search(text)
        if(match):
            player_hp = match.group(1)
        else:
            print("The text file does not contain a HP.")
            return
        print(player_hp)

        # Using system calls to pause output is not a great idea for a 
        # variety of reasons, such as cross OS compatibility
        # Instead of os.system("pause") try
        input("Press enter to continue...")

        save.close()
savetest()

答案 3 :(得分:0)

与其尝试创建和解析专有格式(您很可能会在某个时候遇到限制,并且需要更改逻辑和/或文件格式),不如坚持使用众所周知的定义明确的文件格式包含必需的编写器和解析器,例如yamljsoncfgxml等。

这可以节省很多痛苦;考虑以下具有状态并且可以序列化为键值映射文件格式的类的快速示例(我在这里使用yaml,但是您可以轻松地将其交换为json或其他):

#!/usr/bin/python

import os
import yaml


class GameState:
    def __init__(self, name, **kwargs):
        self.name = name
        self.health = 100

        self.__dict__.update(kwargs)

    @staticmethod
    def from_savegame(path):
        with open(path, 'r') as savegame:
            args = yaml.safe_load(savegame)
            return GameState(**args)

    def save(self, path, overwrite=False):
        if os.path.exists(path) and os.path.isfile(path) and not overwrite:
            raise IOError('Savegame exists; refusing to overwrite.')

        with open(path, 'w') as savegame:
            savegame.write(yaml.dump(self.__dict__))

    def __str__(self):
        return (
            'GameState(\n{}\n)'
            .format(
                '\n'.join([
                    '  {}: {}'.format(k, v)
                    for k, v in self.__dict__.iteritems()
                ]))
        )

示例性地使用此简单类:

SAVEGAMEFILE = 'savegame_01.yml'

new_gs = GameState(name='jbndlr')
print(new_gs)
new_gs.health = 98
print(new_gs)
new_gs.save(SAVEGAMEFILE, overwrite=True)

old_gs = GameState.from_savegame(SAVEGAMEFILE)
print(old_gs)

...产量:

GameState(
  health: 100
  name: jbndlr
)
GameState(
  health: 98
  name: jbndlr
)
GameState(
  health: 98
  name: jbndlr
)