假设你有这样的文字:
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
并且您希望将00
右侧的所有非|
更改为()
,但仅限|
的LHS } 00
。期望的结果:
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
有没有一种很好的方法可以使用sed进行此操作,或者我是否试图超越语言的功能?
到目前为止,这是我的工作:
s/[^0]\{2\}/(&)/g
包装您的RHS值
/[^|]*00[^|]*|/
可用作命令的地址,仅在有效行上运行
现在的诀窍是制定一个在模式空间的一部分中执行的命令。
这实际上不是面向行的,这可以解释为什么我无法获得一个有效的表达式。
答案 0 :(得分:4)
$ awk 'BEGIN{ FS=OFS="|" } $1~/ 00 /{gsub(/[^ ][^0 ]|[^0 ][^ ]/,"(&)",$2)} 1' file
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
如果您要搜索的字符串变得比2 0更复杂,这里是一种更通用的可扩展方法,因为它不需要您编写否定该字符串的RE:
$ awk '
BEGIN{ FS=OFS="|" }
$1 ~ / 00 /{
split($2,a,/ /)
$2=""
for (i=2;i in a;i++)
$2 = $2 " " (a[i] == "00" ? a[i] : "(" a[i] ")")
}
1
' file
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
答案 1 :(得分:3)
这可能适合你(GNU sed):
sed -r '/^\s*\S+\s*00/!b;s/\b([^0][^0]|0[^0]|[^0]0)\b/(&)/g' file
这忽略了不以单词后跟00开头的行。然后插入2个字符串的parens,这些字符串既不是0,也不包含0和非0。
答案 2 :(得分:2)
sed -r '/00.*\|/ { ## match lines with a zero before the pipe
### surround tailing digits with ()
##
s/(\w\w) (\w\w) (\w\w) (\w\w) (\w\w)$/(\1) (\2) (\3) (\4) (\5)/;
### replace the zeroes (00) with 00
##
s/\(00\)/00/g;
}' txt
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
OK!
答案 3 :(得分:1)
好的尝试一下!
$ sed '/00 *|/ { h; s/|.*/|/; x; s/.*|//; s/\(0[1-9a-f]\|[1-9a-f][0-9a-f]\)/(\1)/g; H; x; s/\n//; }' yourfile.txt
我得到的输出是:
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
已编辑,因此在00
之前不会触及|
之前的行。
答案 4 :(得分:1)
我认为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
和t 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)