我正在尝试使用 bash 脚本对文件进行一些文本处理。目标是获取在“attribute:”标签下缩进的所有以“field:”开头的行,并将它们与后面以“- attr:”开头的关联行交换。
到目前为止,我认为我的正则表达式模式应该与标签匹配:
/ *field:(.*)/g
/ *- attr:(.*)/g
但我在解析所需字段并让它们正确交换的逻辑方面还没有取得任何成功。
输入文本示例
- metric: 'example.metric.1'
attributes:
field: 'example 1'
- attr: 'example1'
field: 'example 2'
- attr: 'example2'
field: 'example 3'
- attr: 'example3'
field: 'example 4'
- attr: 'example4'
- metric: 'example.metric.2'
attributes:
field: 'example 5'
- attr: 'example5'
field: 'example 6'
- attr: 'example6'
field: 'example 7'
- attr: 'example7'
- metric: 'example.metric.3'
...
所需输出
- metric: 'example.metric.1'
attributes:
- attr: 'example1'
field: 'example 1'
- attr: 'example2'
field: 'example 2'
- attr: 'example3'
field: 'example 3'
- attr: 'example4'
field: 'example 4'
- metric: 'example.metric.2'
attributes:
- attr: 'example5'
field: 'example 5'
- attr: 'example6'
field: 'example 6'
- attr: 'example7'
field: 'example 7'
- metric: 'example.metric.3'
...
我将如何实现这一目标?
答案1
在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ awk '$1=="field:"{s=ORS $0; next} {print $0 s; s=""}' file
- metric: 'example.metric.1'
attributes:
- attr: 'example1'
field: 'example 1'
- attr: 'example2'
field: 'example 2'
- attr: 'example3'
field: 'example 3'
- attr: 'example4'
field: 'example 4'
- metric: 'example.metric.2'
attributes:
- attr: 'example5'
field: 'example 5'
- attr: 'example6'
field: 'example 6'
- attr: 'example7'
field: 'example 7'
- metric: 'example.metric.3'
如果您在某些行后可能没有空格field:
,或者出于某种原因迫切希望使用正则表达式,则更改为$1=="field:"
或$1~/^field:/
,/^[[:space:]]*field:/
无论您喜欢哪个。
答案2
和sed
:
sed -n '/^ *field: /{h;n;G};p' data
如果我们匹配一个field
关键字,那么:
- 将当前行保存在
hold space
(h
)中 pattern space
从(n
)中的文件中获取下一行- 将
pattern space
与hold space
(G
) 交换(相当于换行)
打印您遇到的每一行:p
答案3
使用awk
:
awk '{if ($1 == "field:") {a=$0;x=0}
else if (/- attr:/) {$0 = $0 ORS a; x=1} else {x=1}}x' input
在此命令中,如果field:
找到,则将当前输入 record( $0
) 保存到变量中a
,并将 x 设置为零。如果attr:
找到,$0
则将 d 更改为 old ,$0
然后是ORS
(newline) ,然后是变量a
。
答案4
我们可以使用 POSIX sed 结构来翻转上述行。
sed '/attr:/!x;$G' file