【问题标题】:Extract numbers between string and second empty line : BASH and python提取字符串和第二个空行之间的数字:BASH 和 python
【发布时间】:2020-07-12 00:56:15
【问题描述】:

问题类似于之前关于 SO 的许多问题。但似乎足够清晰。

我有具有以下输出的数据文件。数字将被提取。数字块中元素的数量是随机的,并且在数字块的上下各有一个空行。目的是提取数字并可能将它们分配给 python numpy 数组。

string 1 

234034 6361234 45096 12342134 2878814 456456
125294 7341234 17234 23135   768234  54134123
213203 6.25 2.36 1.0 0.0021 

string 2 

298034 20481234 45096 12502134 2870814 456456
19875294 441284 98234 27897135 251021524  768234  54134123
2.3261

string 3 

744034 6644034 75096 5302134 298978814 456456
6767294 70441234 330234 200135   867234  54004123
204203 22015 120158 125 21  625 11 5 2.021

预期输出: all 块中的数字排列为 bash 数组或 numpy(python) 数组。 下面显示的数值仅具有代表性。

  • Bash 数组:'744034','6644034','75096', .. .. '21','625','11','5','2.021'

  • Numpy 数组:[744034,6644034,75....,625,11,5,2.021]

    不过,我的用例更喜欢 numpy 数组。


从以前的question 中得到启发,尝试了这个sed -n '/^symmetry 1$/,/^symmetry 2$/p' file 但输出为 null 可能是由于开始和结束搜索词中的空格。


尝试过 python,因为最终我需要将数字作为 np 数组。从question 和 cmets 的帮助中,我使用以下代码得到一个块

import sys
import re
F=open(sys.argv[1])
text=F.read()
reg=re.compile(r'string 1(.*?)string 2',re.DOTALL)
for match in reg.finditer(text):
    print (match.groups())

输出,

string 1 

744034 6644034 75096 5302134 298978814 456456
6767294 70441234 330234 200135   867234  54004123
204203 22015 120158 125 21  625 11 5 2.021

 string 2

需要建议。

【问题讨论】:

  • print match.groups()[0] => print(match.group()),正则表达式必须是r'xxx(.*?)yyy'
  • 谢谢,我现在可以得到一个块。
  • 你想要一个数组中的所有数字吗?
  • @UnbearableLightness : 单独的数组更好。

标签: python python-3.x bash awk sed


【解决方案1】:

如果我理解得很好,这可能会有所帮助:

>>> [np.array(block.split()).astype(float)  # good blocks get parsed into np arrays
     for block in file_content.split("\n\n")  # split by empty lines
     if not block[0].isalpha()]  # avoid string lines                                                                                   

[array([2.3403400e+05, 6.3612340e+06, 4.5096000e+04, 1.2342134e+07,
        2.8788140e+06, 4.5645600e+05, 1.2529400e+05, 7.3412340e+06,
        1.7234000e+04, 2.3135000e+04, 7.6823400e+05, 5.4134123e+07,
        2.1320300e+05, 6.2500000e+00, 2.3600000e+00, 1.0000000e+00,
        2.1000000e-03]),
 array([2.98034000e+05, 2.04812340e+07, 4.50960000e+04, 1.25021340e+07,
        2.87081400e+06, 4.56456000e+05, 1.98752940e+07, 4.41284000e+05,
        9.82340000e+04, 2.78971350e+07, 2.51021524e+08, 7.68234000e+05,
        5.41341230e+07, 2.32610000e+00]),
 array([7.44034000e+05, 6.64403400e+06, 7.50960000e+04, 5.30213400e+06,
        2.98978814e+08, 4.56456000e+05, 6.76729400e+06, 7.04412340e+07,
        3.30234000e+05, 2.00135000e+05, 8.67234000e+05, 5.40041230e+07,
        2.04203000e+05, 2.20150000e+04, 1.20158000e+05, 1.25000000e+02,
        2.10000000e+01, 6.25000000e+02, 1.10000000e+01, 5.00000000e+00,
        2.02100000e+00])]

【讨论】:

  • 看起来不错。将尝试。
  • 也许过滤器避免字符串行不够强大,因为我只检查第一个字符,字符串行可能以数字开头。告诉我这是否是个问题。
  • @ankit7540 如果解决方案对您有用,您可以接受答案。谢谢
  • 在剥离- 的字符串后,它就可以工作了。
  • 您也可以使用 if any([c.isalpha() for c in block[:3]] 来检查前 3 个字符...如果它有效,那就太好了!
【解决方案2】:

您没有显示预期的输出,但这是您想要做的吗?

$ awk -v RS= '!(NR%2)' file
234034 6361234 45096 12342134 2878814 456456
125294 7341234 17234 23135   768234  54134123
213203 6.25 2.36 1.0 0.0021
298034 20481234 45096 12502134 2870814 456456
19875294 441284 98234 27897135 251021524  768234  54134123
2.3261
744034 6644034 75096 5302134 298978814 456456
6767294 70441234 330234 200135   867234  54004123
204203 22015 120158 125 21  625 11 5 2.021

或者可能是其中之一(或其他东西 - 告诉....):

$ awk -v RS= -v ORS='\n\n' '!(NR%2)' file
234034 6361234 45096 12342134 2878814 456456
125294 7341234 17234 23135   768234  54134123
213203 6.25 2.36 1.0 0.0021

298034 20481234 45096 12502134 2870814 456456
19875294 441284 98234 27897135 251021524  768234  54134123
2.3261

744034 6644034 75096 5302134 298978814 456456
6767294 70441234 330234 200135   867234  54004123
204203 22015 120158 125 21  625 11 5 2.021

.

$ awk -v RS= -v OFS='\n' '!(NR%2){$1=$1; print}' file
234034
6361234
45096
12342134
2878814
456456
125294
7341234
17234
23135
768234
54134123
213203
6.25
2.36
1.0
0.0021
298034
20481234
45096
12502134
2870814
456456
19875294
441284
98234
27897135
251021524
768234
54134123
2.3261
744034
6644034
75096
5302134
298978814
456456
6767294
70441234
330234
200135
867234
54004123
204203
22015
120158
125
21
625
11
5
2.021

【讨论】:

  • 我试图让数字形成不同的块作为数组。由于块中的元素数量不统一,因此 awk 方法不太适合。
  • 我不知道那是什么意思。如果您 edit 您的问题是显示预期输出,无论它是什么,我都可以向您展示如何使用 awk 获得该输出。我在您的问题中的“输出”标题下看到了一些内容,但我看不到那里的值与您提供的输入中的值有何关联(例如,-20.73386803 来自哪里?)我看到了“string1”当您说您只想获取数字时出现在那里,所以我不清楚这是给定您发布的示例输入的实际所需输出,或者,如果是,它是如何从一个映射到另一个的。
  • 感谢您的评论。对不起这是我的错。输出文件有几十个这样的块,我展示了一个这样的块的输出。会修复它。所需的输出已被修改。
  • 那么您在“string1”下的预期输出是输入中“string3”下的数字块不变吗?老实说,我不知道你想做什么,抱歉。
  • 对不起,我这边沟通不畅,预期的输出是所有数字块作为数组。
猜你喜欢
  • 2021-10-15
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-15
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
相关资源
最近更新 更多