python-3.x 将行拆分为变量

ht4b089n  于 2023-02-01  发布在  Python
关注(0)|答案(4)|浏览(136)

我正在尝试将一个包含多行的txt文件拆分为单独的变量。文本是卷信息的输出,其中包含名称、数据大小等。我想将每个数据集拆分为特定变量,但似乎无法获得该变量
示例试图将此数据集拆分为每个项目的变量

/vol0                                abcd4     Object RAID6+  228.33 GB         --  400.00 GB  Online
/vole1                               abcd1     Object RAID6+   44.19 TB   45.00 TB   45.00 TB  Online
/vole2                               abcd4     Object RAID6+   11.27 TB   11.00 TB   12.00 TB  Online
/vol3                                abcd4     Object RAID6+    9.50 TB         --   10.00 TB  Online
/vol4                                abcd1     Object RAID6+   18.39 TB         --   19.10 TB  Online

这是我运行的命令,但我一直收到关于“not enough values to unpack“的错误。

inputfile = "dataset_input.txt"
with open(inputfile, "r") as input:
    for row in input:
        vol, bs, obj, raid, used, uunit, quota, qunit, q2, q2unit, status = row.split()

我可以通过下面的文本按空格分割文件,它可以工作。只是看起来不能把它放入单独的变量中,这样我就可以操纵数据集了

for row in input: #running through each row in the file
    output_text = row.split() #split the row based on the default white-space delimiter
    print(output_text)

我对python非常陌生,所以不确定这是否可行,也不确定它有多复杂

x7yiwoj4

x7yiwoj41#

首先你要做的是调用split方法,它会把你的行拆分成一个列表,对应字符串中的每一个空格,这会给你提供一个比你定义的变量数更长的列表,这只能通过拆分成你需要的变量数来解决。
其次,在每个for循环中,相同的变量将被重写为新值,从而丢失先前的迭代值,您可以通过将值追加到相应的变量数组中来解决此问题
下面是一个简单的解决方案,首先读取整个文本文件内容,对其进行预处理,然后将处理后的内容存储到所需的变量列表中

fle=open("dataset_input.txt",'r')
txt=fle.readlines()

#adding another newline for patter homogenity
txt[-1]+='\n'

n=len(txt)

#remove new lines 
for i in range(0,n):txt[i]=txt[i][0:-1]

#trim multi spaces to #
import re
for i in range(0,n):
    txt[i]=re.sub('\s{2,}','#',txt[i])
    txt[i]=txt[i].split('#')

#define required variables
x1=[]
x2=[]
x3=[]
x4=[]
x5=[]
x6=[]
x7=[]

#adding the variable values to respective variables
for i in txt:
    x1.append(i[0])
    x2.append(i[1])
    x3.append(i[2])
    x4.append(i[3])
    x5.append(i[4])
    x6.append(i[5])
    x7.append(i[6])

print(x1,x2,x3,x4,x5,x6,x7)

还要注意的是,可以根据主文本文件内容的生命周期要求,通过组合在预处理阶段追加的列表来改进代码

bkhjykvo

bkhjykvo2#

执行以下代码行时产生错误 * not enough values to unpack *:vol, bs, obj, raid, used, uunit, quota, qunit, q2, q2unit, status = row.split().原因是你正在从每行读取11个单独的元素,尽管看看你展示的例子,并不是每行都包含11个由空格分隔的单词。检查一下:

with open(inputfile, "r") as input:
    for row in input:
        output = row.split()
        print("this row provides {} arguments".format(len(output)))
        print(output)

输出:

this row provides 10 arguments
['/vol0', 'abcd4', 'Object', 'RAID6+', '228.33', 'GB', '--', '400.00', 'GB', 'Online']
this row provides 11 arguments
['/vole1', 'abcd1', 'Object', 'RAID6+', '44.19', 'TB', '45.00', 'TB', '45.00', 'TB', 'Online']
this row provides 11 arguments
['/vole2', 'abcd4', 'Object', 'RAID6+', '11.27', 'TB', '11.00', 'TB', '12.00', 'TB', 'Online']
this row provides 10 arguments
['/vol3', 'abcd4', 'Object', 'RAID6+', '9.50', 'TB', '--', '10.00', 'TB', 'Online']
this row provides 10 arguments
['/vol4', 'abcd1', 'Object', 'RAID6+', '18.39', 'TB', '--', '19.10', 'TB', 'Online']

你需要对你的数据集做一些清理或者也许长度上的if语句会有帮助。只看你提供的数据的一小部分,我看到标记**"--"意味着没有卷。所以你可以用一对有意义的变量替换"--"**标记(值+单位),例如0和任何单位。您可以这样做:

with open(inputfile, "r") as input:
        for row in input:
            output = str(row).replace("--","0 0").split()
            print("this row provides {} arguments".format(len(output)))
            print(output)

这就是输出

this row provides 11 arguments
['/vol0', 'abcd4', 'Object', 'RAID6+', '228.33', 'GB', '0', '0', '400.00', 'GB', 'Online']
this row provides 11 arguments
['/vole1', 'abcd1', 'Object', 'RAID6+', '44.19', 'TB', '45.00', 'TB', '45.00', 'TB', 'Online']
this row provides 11 arguments
['/vole2', 'abcd4', 'Object', 'RAID6+', '11.27', 'TB', '11.00', 'TB', '12.00', 'TB', 'Online']
this row provides 11 arguments
['/vol3', 'abcd4', 'Object', 'RAID6+', '9.50', 'TB', '0', '0', '10.00', 'TB', 'Online']
this row provides 11 arguments
['/vol4', 'abcd1', 'Object', 'RAID6+', '18.39', 'TB', '0', '0', '19.10', 'TB', 'Online']
biswetbf

biswetbf3#

在我看来,你的数据是一个定长记录的列表,而不是使用split(),你可以根据你的定长字段来获取切片。Ultimatley,我会考虑使用pythons struct来实现,但这可能会让你开始处理定长记录。
让我们从文件中读取的一些示例数据开始,定义一个定长字段规范列表。

data = [
    "/vol0                                abcd4     Object RAID6+  228.33 GB         --  400.00 GB  Online",
    "/vole1                               abcd1     Object RAID6+   44.19 TB   45.00 TB   45.00 TB  Online",
    "/vole2                               abcd4     Object RAID6+   11.27 TB   11.00 TB   12.00 TB  Online",
    "/vol3                                abcd4     Object RAID6+    9.50 TB         --   10.00 TB  Online",
    "/vol4                                abcd1     Object RAID6+   18.39 TB         --   19.10 TB  Online"
]

##------------------------------
## Only you know for sure what the start and stop is of the fields in this fixed length record.
##------------------------------
fields = [
    {"name": "path", "starts_at": 0, "width": 37},
    {"name": "abc", "starts_at": 37, "width": 5},
    {"name": "type", "starts_at": 47, "width": 13},
    {"name": "size", "starts_at": 60, "width": 11},
    # ....
]
##------------------------------

现在,给定数据行和字段定义,我们可以创建一个列表的列表。

##------------------------------
## reshape as a list of lists
##------------------------------
data2 = [
    [
        row[field["starts_at"] : field["starts_at"] + field["width"]].strip()
        for field
        in fields
    ]
    for row
    in data
]
print(json.dumps(data2, indent=2))
##------------------------------

这将为您提供:

[
    ['/vol0', 'abcd4', 'Object RAID6+', '228.33 GB'],
    ['/vole1', 'abcd1', 'Object RAID6+', '44.19 TB'],
    ['/vole2', 'abcd4', 'Object RAID6+', '11.27 TB'],
    ['/vol3', 'abcd4', 'Object RAID6+', '9.50 TB'],
    ['/vol4', 'abcd1', 'Object RAID6+', '18.39 TB']
]

如果可能的话,我自己更愿意使用dictlist,因此,考虑到上面的数据和字段定义,我可能会这样使用它们......

##------------------------------
## reshape as a list of dict
##------------------------------
data2 = [
    {
        field["name"]: row[field["starts_at"] : field["starts_at"] + field["width"]].strip()
        for field
        in fields
    }
    for row
    in data

]

import json # only for printing a nice output
print(json.dumps(data2, indent=2))
##------------------------------

为您提供:

[
  {
    "path": "/vol0",
    "abc": "abcd4",
    "type": "Object RAID6+",
    "size": "228.33 GB"
  },
  {
    "path": "/vole1",
    "abc": "abcd1",
    "type": "Object RAID6+",
    "size": "44.19 TB"
  },
  {
    "path": "/vole2",
    "abc": "abcd4",
    "type": "Object RAID6+",
    "size": "11.27 TB"
  },
  {
    "path": "/vol3",
    "abc": "abcd4",
    "type": "Object RAID6+",
    "size": "9.50 TB"
  },
  {
    "path": "/vol4",
    "abc": "abcd1",
    "type": "Object RAID6+",
    "size": "18.39 TB"
  }
]
qyuhtwio

qyuhtwio4#

如果你想保持你原来的方法,像这样的东西将迎合有时只有10个'列'而不是预期的11个错误:

with open('dataset_input.txt') as f:
    lines = f.readlines()

for line in lines:
    line = line.strip().split()  # Remove white space and split by space, returns a list
    if line[6] == '--':
        # This means there is no quota value present
        # so insert another -- to correct the length ('columns') of the line to 11
        line.insert(6, '--')
    vol, bs, obj, raid, used, uunit, quota, qunit, q2, q2unit, status = tuple(line)
    # Perform any calculations and prints you want here 
    # PER LINE (each iteration will overwrite the variables above)
    # Note that all variables will be strings. So convert if required.

你当然可以把“--”改成任何你想要的。例如:

...
line.insert(6, '0')
...

如果您愿意,还可以更改qunit中的“--”:

...
line[6] = '0'
line.insert(6, '0')
...

另一方面,在原始代码中,文件句柄是inputinput是Python的保留关键字;在代码中选择任何类型的标识符时,都应该避免这些问题。

相关问题