我认为awk
这可能是这项工作的更好工具,但可以通过以下方式完成sed
:
sed '/^[^ ]* *00 *|/{
:a
s/\(|.*[^(]\)\([0-9a-f][1-9a-f]\)/\1(\2)/
t a
:b
s/\(|.*[^(]\)\([1-9a-f][0-9a-f]\)/\1(\2)/
t b
}' data
该脚本查找包含00
在管道之前的行,并且仅将操作应用于这些行。有两个替代操作,每个都包裹在一个循环中。和:a
线:b
是标签。如果自上次跳转后执行了替换,则t a
andt b
命令是到指定标签的条件跳转。这两个替换几乎是对称的;第一个处理任何不以 0 结尾的数字;第二个处理任何不以 0 开头的数字;他们之间,他们忽略了00
。这些模式查找管道、任何不以左括号结尾的字符序列(
以及适当的数字对;它替换了它,以便数字在括号内结束。循环是必要的,因为g
修饰符不再从头开始,并且模式通过数字向后工作。
鉴于此数据文件(您的稍微扩展的版本):
foobar 42 | ff 00 00 00 00
foobaz 00 | 0a 00 0b 00 00
foobie 00 | 00 00 00 00 00
bar 00 | ab ba 00 cd 00
fizbie 00 | ab ba 00 cd 90
fizzbuzz 00 | ab ba 00 cd 09
脚本的输出是:
foobar 42 | ff 00 00 00 00
foobaz 00 | (0a) 00 (0b) 00 00
foobie 00 | 00 00 00 00 00
bar 00 | (ab) (ba) 00 (cd) 00
fizbie 00 | (ab) (ba) 00 (cd) (90)
fizzbuzz 00 | (ab) (ba) 00 (cd) (09)
在每个替换命令之后添加一个具有中等教育p
意义的,因此您可以看到替换是如何工作的:
foobar 42 | ff 00 00 00 00
foobaz 00 | 0a 00 (0b) 00 00
foobaz 00 | (0a) 00 (0b) 00 00
foobaz 00 | (0a) 00 (0b) 00 00
foobie 00 | 00 00 00 00 00
bar 00 | ab ba 00 (cd) 00
bar 00 | ab (ba) 00 (cd) 00
bar 00 | (ab) (ba) 00 (cd) 00
bar 00 | (ab) (ba) 00 (cd) 00
fizbie 00 | ab ba 00 (cd) 90
fizbie 00 | ab (ba) 00 (cd) 90
fizbie 00 | (ab) (ba) 00 (cd) 90
fizbie 00 | (ab) (ba) 00 (cd) (90)
fizbie 00 | (ab) (ba) 00 (cd) (90)
fizzbuzz 00 | ab ba 00 cd (09)
fizzbuzz 00 | ab ba 00 (cd) (09)
fizzbuzz 00 | ab (ba) 00 (cd) (09)
fizzbuzz 00 | (ab) (ba) 00 (cd) (09)
fizzbuzz 00 | (ab) (ba) 00 (cd) (09)