- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我试图将元素与多行字符串分开:
lines = '''c0 c1 c2 c3 c4 c5
0 10 100.5 [1.5, 2] [[10, 10.4], [c, 10, eee]] [[a , bg], [5.5, ddd, edd]] 100.5
1 20 200.5 [2.5, 2] [[20, 20.4], [d, 20, eee]] [[a , bg], [7.5, udd, edd]] 200.5'''
我的目标是得到一个列表 lst
这样:
# first value is index
lst[0] = ['c0', 'c1', 'c2', 'c3', 'c4','c5']
lst[1] = [0, 10, 100.5, [1.5, 2], [[10, 10.4], ['c', 10, 'eee']], [['a' , 'bg'], [5.5, 'ddd', 'edd']], 100.5 ]
lst[2] = [1, 20, 200.5, [2.5, 2], [[20, 20.4], ['d', 20, 'eee']], [['a' , 'bg'], [7.5, 'udd', 'edd']], 200.5 ]
到目前为止我的尝试是这样的:
import re
lines = '''c0 c1 c2 c3 c4 c5
0 10 100.5 [1.5, 2] [[10, 10.4], [c, 10, eee]] [[a , bg], [5.5, ddd, edd]] 100.5
1 20 200.5 [2.5, 2] [[20, 20.4], [d, 20, eee]] [[a , bg], [7.5, udd, edd]] 200.5'''
# get n elements for n lines and remove empty lines
lines = lines.split('\n')
lines = list(filter(None,lines))
lst = []
lst.append(lines[0].split())
for i in range(1,len(lines)):
change = re.sub('([a-zA-Z]+)', r"'\1'", lines[i])
lst.append(change)
for i in lst[1]:
print(i)
如何修复正则表达式?
更新
测试数据集
data = """
orig shifted not_equal cumsum lst
0 10 NaN True 1 [[10, 10.4], [c, 10, eee]]
1 10 10.0 False 1 [[10, 10.4], [c, 10, eee]]
2 23 10.0 True 2 [[10, 10.4], [c, 10, eee]]
"""
# Gives: ValueError: malformed node or string:
data = """
Name Result Value
0 Name1 5 2
1 Name1 5 3
2 Name2 11 1
"""
# gives same error
data = """
product value
0 A 25
1 B 45
2 C 15
3 C 14
4 C 13
5 B 22
"""
# gives same error
data = '''
c0 c1
0 10 100.5
1 20 200.5
'''
# works perfect
最佳答案
如评论中所述,使用正则表达式无法完成此任务。正则表达式根本无法处理嵌套结构。您需要的是解析器。
创建解析器的方法之一是 PEG ,它允许您以声明性语言设置 token 列表及其相互关系。然后将此解析器定义转换为可以处理所描述输入的实际解析器。解析成功后,您将得到一个正确嵌套了所有项的树结构。
出于演示目的,我使用了 JavaScript 实现 peg.js,它有一个 online demo page您可以在其中针对某些输入实时测试解析器。此解析器定义:
{
// [value, [[delimiter, value], ...]] => [value, value, ...]
const list = values => [values[0]].concat(values[1].map(i => i[1]));
}
document
= line*
line "line"
= value:(item (whitespace item)*) whitespace? eol { return list(value) }
item "item"
= number / string / group
group "group"
= "[" value:(item (comma item)*) whitespace? "]" { return list(value) }
comma "comma"
= whitespace? "," whitespace?
number "number"
= value:$[0-9.]+ { return +value }
string "string"
= $([^ 0-9\[\]\r\n,] [^ \[\]\r\n,]*)
whitespace "whitespace"
= $" "+
eol "eol"
= [\r]? [\n] / eof
eof "eof"
= !.
可以理解这种输入:
c0 c1 c2 c3 c4 c50 10 100.5 [1.5, 2] [[10, 10.4], [c, 10, eee]] [[a , bg], [5.5, ddd, edd]]1 20 200.5 [2.5, 2] [[20, 20.4], [d, 20, eee]] [[a , bg], [7.5, udd, edd1]]
and produces this object tree (JSON notation):
[
["c0", "c1", "c2", "c3", "c4", "c5"],
[0, 10, 100.5, [1.5, 2], [[10, 10.4], ["c", 10, "eee"]], [["a", "bg"], [5.5, "ddd", "edd"]]],
[1, 20, 200.5, [2.5, 2], [[20, 20.4], ["d", 20, "eee"]], [["a", "bg"], [7.5, "udd", "edd1"]]]
]
即
然后您的程序可以处理此树结构。
上面的示例可以与 node.js 一起使用,将您的输入转换为 JSON。下面的最小 JS 程序从 STDIN 接受数据并将解析结果写入 STDOUT:
// reference the parser.js file, e.g. downloaded from https://pegjs.org/online
const parser = require('./parser');
var chunks = [];
// handle STDIN events to slurp up all the input into one big string
process.stdin.on('data', buffer => chunks.push(buffer.toString()));
process.stdin.on('end', function () {
var text = chunks.join('');
var data = parser.parse(text);
var json = JSON.stringify(data, null, 4);
process.stdout.write(json);
});
// start reading from STDIN
process.stdin.resume();
将它保存为 text2json.js
或类似的东西并将一些文本重定向(或管道)到其中:
# input redirection (this works on Windows, too)
node text2json.js < input.txt > output.json
# common alternative, but I'd recommend input redirection over this
cat input.txt | node text2json.js > output.json
还有用于 Python 的 PEG 解析器生成器,例如 https://github.com/erikrose/parsimonious .解析器创建语言因实现而异,所以以上只能用于peg.js,但原理是完全一样的。
编辑 我深入研究了 Parsimonious,并在 Python 代码中重新创建了上述解决方案。方法是一样的,解析器语法是一样的,只是有一些微小的语法变化。
from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor
grammar = Grammar(
r"""
document = line*
line = whitespace? item (whitespace item)* whitespace? eol
item = group / number / boolean / string
group = "[" item (comma item)* whitespace? "]"
comma = whitespace? "," whitespace?
number = "NaN" / ~"[0-9.]+"
boolean = "True" / "False"
string = ~"[^ 0-9\[\]\r\n,][^ \[\]\r\n,]*"
whitespace = ~" +"
eol = ~"\r?\n" / eof
eof = ~"$"
""")
class DataExtractor(NodeVisitor):
@staticmethod
def concat_items(first_item, remaining_items):
""" helper to concat the values of delimited items (lines or goups) """
return first_item + list(map(lambda i: i[1][0], remaining_items))
def generic_visit(self, node, processed_children):
""" in general we just want to see the processed children of any node """
return processed_children
def visit_line(self, node, processed_children):
""" line nodes return an array of their processed_children """
_, first_item, remaining_items, _, _ = processed_children
return self.concat_items(first_item, remaining_items)
def visit_group(self, node, processed_children):
""" group nodes return an array of their processed_children """
_, first_item, remaining_items, _, _ = processed_children
return self.concat_items(first_item, remaining_items)
def visit_number(self, node, processed_children):
""" number nodes return floats (nan is a special value of floats) """
return float(node.text)
def visit_boolean(self, node, processed_children):
""" boolean nodes return return True or False """
return node.text == "True"
def visit_string(self, node, processed_children):
""" string nodes just return their own text """
return node.text
DataExtractor
负责遍历树并从节点中提取数据,返回字符串、数字、 bool 值或 NaN 的列表。
concat_items()
函数执行与上面 Javascript 代码中的 list()
函数相同的任务,其他函数在 peg.js 中也有它们的等价物方法,除了 peg.js 将它们直接集成到解析器定义中,Parsimonious 期望定义在一个单独的类中,所以相比之下它有点冗长,但还不错。
用法,假设一个名为“data.txt”的输入文件,也反射(reflect)了 JS 代码:
de = DataExtractor()
with open("data.txt", encoding="utf8") as f:
text = f.read()
tree = grammar.parse(text)
data = de.visit(tree)
print(data)
输入:
orig shifted not_equal cumsum lst0 10 NaN True 1 [[10, 10.4], [c, 10, eee]]1 10 10.0 False 1 [[10, 10.4], [c, 10, eee]]2 23 10.0 True 2 [[10, 10.4], [c, 10, eee]]
输出:
[ ['orig', 'shifted', 'not_equal', 'cumsum', 'lst'], [0.0, 10.0, nan, True, 1.0, [[10.0, 10.4], ['c', 10.0, 'eee']]], [1.0, 10.0, 10.0, False, 1.0, [[10.0, 10.4], ['c', 10.0, 'eee']]], [2.0, 23.0, 10.0, True, 2.0, [[10.0, 10.4], ['c', 10.0, 'eee']]]]
从长远来看,我希望这种方法比 regex hackery 更易于维护和灵活。例如,添加对 NaN 和 bool 值(上面的 peg.js-Solution 没有 - 它们被解析为字符串)的显式支持很容易。
关于python - 高级 Python 正则表达式 : how to evaluate and extract nested lists and numbers from a multiline string?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53531519/
我正在用 yacc/bison 编写一个简单的计算器。 表达式的语法看起来有点像这样: expr : NUM | expr '+' expr { $$ = $1 + $3; } | expr '-'
我开始学习 lambda 表达式,并在以下情况下遇到了以下语句: interface MyNumber { double getValue(); } MyNumber number; nu
这两个 Linq 查询有什么区别: var result = ResultLists().Where( c=> c.code == "abc").FirstOrDefault(); // vs. va
如果我们查看 draft C++ standard 5.1.2 Lambda 表达式 段 2 说(强调我的 future ): The evaluation of a lambda-expressio
我使用的是 Mule 4.2.2 运行时、studio 7.5.1 和 Oracle JDK 1.8.0_251。 我在 java 代码中使用 Lambda 表达式,该表达式由 java Invoke
我是 XPath 的新手。我有网页的html源 http://london.craigslist.co.uk/com/1233708939.html 现在我想从上面的页面中提取以下数据 完整日期 电子
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭10 年前。 Improve th
我将如何编写一个 Cron 表达式以在每天上午 8 点和下午 3:30 触发?我了解如何创建每天触发一次的表达式,而不是在多个设定时间触发。提前致谢 最佳答案 你应该只使用两行。 0 8 * * *
这个问题已经有答案了: What do 3 dots next to a parameter type mean in Java? (9 个回答) varargs and the '...' argu
我是 python 新手,在阅读 BeautifulSoup 教程时,我不明白这个表达式“[x for x in titles if x.findChildren()][:-1]”我不明白?你能解释一
(?:) 这是一个有效的 ruby 正则表达式,谁能告诉我它是什么意思? 谢谢 最佳答案 正如其他人所说,它被用作正则表达式的非捕获语法,但是,它也是正则表达式之外的有效 ruby 语法。 在
这个问题在这里已经有了答案: Why does ++[[]][+[]]+[+[]] return the string "10"? (10 个答案) 关闭 8 年前。 谁能帮我处理这个 JavaSc
这个问题在这里已经有了答案: What is the "-->" operator in C++? (29 个答案) Java: Prefix/postfix of increment/decrem
这个问题在这里已经有了答案: List comprehension vs. lambda + filter (16 个答案) 关闭 10 个月前。 我不确定我是否需要 lambda 或其他东西。但是,
C 中的 assert() 函数工作原理对我来说就像一片黑暗的森林。根据这里的答案https://stackoverflow.com/a/1571360 ,您可以使用以下构造将自定义消息输出到您的断言
在this页,John Barnes 写道: If the conditional expression is the argument of a type conversion then effec
我必须创建一个调度程序,它必须每周从第一天上午 9 点到第二天晚上 11 点 59 分运行 2 天(星期四和星期五)。为此,我需要提供一个 cron 表达式。 0-0 0-0 9-23 ? * THU
我正在尝试编写一个 Linq 表达式来检查派生类中的属性,但该列表由来自基类的成员组成。下面的示例代码。以“var list”开头的 Process 方法的第二行无法编译,但我不确定应该使用什么语法来
此 sed 表达式将输入字符串转换为两行输出字符串。两条输出行中的每一行都由输入的子串组成。第一行需要转换成大写: s:random_stuff\(choice1\|choice2\){\([^}]*
我正在使用 Quartz.Net 在我的应用程序中安排我的工作。我只是想知道是否可以为以下场景构建 CRON 表达式: Every second between 2:15AM and 5:20AM 最
我是一名优秀的程序员,十分优秀!