我有一个包含多个段落的文件,这些段落使用括号作为分隔符,如下所示
{
KEYWORD
a = 1
b = 2
c = 3
}
{
d = 4
KEYWORD
e = 5
f = 6
}
我想循环每个段落并将其分配给变量 $foo 同时保留换行符,因此 echo $foo 将导致该段落以多行格式输出。处理 $foo 的输出后,例如echo $foo | grep bar
程序应该转到下一段并覆盖 $foo
我一直在使用 awk,因为它似乎是这种情况下最好的工具,但我不知道如何执行某种 while 循环,以便我可以单独处理每个段落。
到目前为止我所拥有的是:
grep -Pzo "{[^}]*KEYWORD[^}]*}" FILENAME | awk "/{/{flag=1;
paragraph=\"\"; next} /}/{flag=0; print paragraph} flag {paragraph =
paragraph \$0 \"\\n\"}"
这会产生像这样整齐的段落
KEYWORD
a = 1
b = 2
c = 3
d = 4
KEYWORD
e = 5
f = 6
我陷入困境的是,我想在继续第 2 段之前对第 1 段执行进一步的操作。
我最接近的解决方案是将结果写入数组,但后来我丢失了该段落,所有内容都在一行上,并且我无法进行我想要的匹配后处理。
更新:
本着有不止一种方法可以做到这一点的精神,如果你只有一把锤子,那么一切看起来都像钉子,我提供我的解决方案:
# Read paragraphs into an array
while IFS= read -r paragraph; do
paragraphs+=("$paragraph")
done < <(awk '/\{/{flag=1; paragraph=""; next} /\}/{flag=0; print paragraph} flag {paragraph = paragraph $0}' testoutput.txt)
# Print each paragraph separately
for ((i=0; i<${#paragraphs[@]}; i++)); do
# Assign each paragraph to a variable using eval
eval "foo_$i=\"${paragraphs[$i]}\""
# Print the variable recreating the line breaks
echo "Variable foo_$i:"
eval "echo \"\$foo_$i\"|sed 's/\s\{2,\}/\n/g'"
done
成功的关键是使用 sed's/\s\{2,\}/\n/g'
而不是\s
or\s+
或一个或多个 vs 两个或多个。
这是一种
while
在输入文件的行上使用循环的方法。这些行被读read -r
入变量中line
。如果是 a{
,则重置变量foo
。如果它是 a}
,则执行某些操作$foo
(在这里,我打印其原始内容、长度和一些静态文本)。在任何其他情况下,将 的内容附加line
到 的当前内容foo
。修改 OP 的当前
awk
脚本以在单行上生成每个段落,其中嵌入的换行符 ( ) 被文字字符+\n
替换:\
n
针对示例输入运行此命令:
然后我们可以将这些输入到
bash
内置变量中printf
以填充变量foo
:注意:
printf -v
需要bash 3.1+
这会生成:
一种用于
mapfile
将“段落”读入数组的想法:有一些有趣的项目:
0
2
最后一个条目之后的所有内容}
\n
我们需要删除一个前导考虑到这些问题......
bash/for
一次处理一个“段落”的一个循环这会生成:
注意:
{
如果文件的格式与示例中所示不完全一致(例如,真实文件包含空行;和字符之前/之后有额外的空格}
,则这可能无法按预期工作和/或您可能需要执行一些操作附加参数替换以按摩foo
成所需的格式。{\n
用于删除和的一些附加参数替换的示例}\n
:这会生成:
我会做什么:
这个想法是分割字符上的输出
{\n
以在awk
.