【发布时间】:2020-06-09 23:34:50
【问题描述】:
编辑 2:
最小输入文件:input/input.txt
#-----------
snapshot=83
#-----------
time=30142088
mem_heap_B=20224
mem_heap_extra_B=8
mem_stacks_B=240480
heap_tree=empty
#-----------
snapshot=84
#-----------
time=30408368
mem_heap_B=20224
mem_heap_extra_B=8
mem_stacks_B=240552
heap_tree=empty
#-----------
snapshot=85
#-----------
time=30674648
mem_heap_B=20224
mem_heap_extra_B=8
mem_stacks_B=240464
heap_tree=empty
#-----------
snapshot=86
#-----------
实际输出:
input.txt/*
time, heap, stack
input/input.txt
time, heap, stack
30674648, 20224, 240464
input/input.txt
time, heap, stack
input/input.txt
time, heap, stack
input/input.txt
time, heap, stack
30674648, 20224, 240464
预期输出:
input.txt
time, heap, stack,
30142088, 20224, 240480
30408368, 20224, 240552
30674648, 20224, 240464
编辑:最初,问题可能是由于 Bash 的正则表达式缺乏多行功能。但是,从文本中删除换行符后,问题仍然存在,只是输出现在有 1 到 5 行而不是 0 行。
我正在尝试编写一个 Bash 脚本来将文本文件解析为具有所需信息的所需 CSV 文件。
作为脚本的一部分,我会遍历 n 个文件。每个文件都包含给定正则表达式的 m 个匹配项,每个匹配项包含三个捕获组。
我想将三个捕获组格式化为一个CSV行,然后将所有文件的所有匹配项的所有行连接起来,并将它们写入一个*.csv文件。
我很喜欢在 Kotlin 或 C# 等高级语言中使用 Regex,但是我没有在 Bash 中使用 Regex 的经验。我使用this 回答作为起点,但它似乎对我不起作用(mapfile -t matches < <( format_row "$text" "$regex" ) 没有做任何事情。
这里是完整的代码,相关部分注明:
#!/bin/bash
# RELEVANT CODE BELOW
regex="time=([0-9]+)\nmem_heap_B=([0-9]+)\n.*\nmem_stacks_B=([0-9]+)"
format_row() {
local s=$1 regex=$2
while [[ $s =~ $regex ]]
do
time="${BASH_REMATCH[1]}"
heap="${BASH_REMATCH[2]}"
stack="${BASH_REMATCH[3]}"
echo "${time}, ${heap}, ${stack}"
echo ""
s=${s#*"${BASH_REMATCH[3]}"}
done
}
for file in $1/*
do
echo "Parsing ${file}..."
echo $file >> $2
echo "time, heap, stack" >> $2
text=$(<${file})
mapfile -t matches < <( format_row "$text" "$regex" )
printf "%s\n" "${matches[@]}" >> $2
echo "" >> $2
done
echo ""
echo "Done"
谢谢!
【问题讨论】:
-
只隔离有问题的代码而不是整个脚本怎么样?请阅读MCVE。 bash 正则表达式不支持多行模式
-
可能发生的情况是您假设您知道 bash 实现的正则表达式语言。它可能与您习惯的完全不同。不知道 bash 用什么,不过可能和linuxize.com/post/regular-expressions-in-grep类似
-
perl 可能会为您提供更像您习惯的结果?
-
@JoelFan ya 我认为事实证明就是这样,我习惯于使用“标准”高级正则表达式。谢谢!
-
我认为他们建议使用 perl,而不是 bash 或 grep