Joh*_*809 5 linux bash merge awk sed
我想在 Linux 中屏蔽文件中的位,如下所示:
actual : 00-00000000-00000011-00110010-10000000
expect : 00-00000000-00000001-01101010-00000000
error : 00-00000000-00000010-01011000-00000000
Run Code Online (Sandbox Code Playgroud)
在输出中,该actual部分应该保持原样,除非,error然后1位actual应该被屏蔽X
可以看出,error是和数据的异或。actualexpected
输出应该看起来像这样:
output : 00-00000000-000000X1-0X1XX010-10000000
Run Code Online (Sandbox Code Playgroud)
是否可以使用 SED、AWK 等命令来执行此操作?
到目前为止做了什么:
grep 'err' gpbat | sed 's?-??g' | cut -c 11-35 | sed 's?1?X?g' > a1
grep 'act' gpbat | sed 's?-??g' | cut -c 11- > a2
Run Code Online (Sandbox Code Playgroud)
但从这里开始,不知道如何合并a1&a2
对于许多版本的 awk:
awk '
/actual/ { split($3,a,"") }
/error/ { split($3,e,"") }
END {
for (i in a)
c[i] = e[i]==1 ? "X" : a[i]
for (i = length(c); i>0; --i)
s = c[i] s
printf "output : %s\n", s
}
' gpbat
Run Code Online (Sandbox Code Playgroud)
POSIX 指出splitonempty string 的结果是未定义的行为“以允许提议的未来扩展将字符串拆分为单个字符数组”,但我个人还没有遇到过尚未这样做的版本。YMMV。为了实现完全的可移植性,@markp-fuso 的方法使用substr将是首选。
或者稍微更有效(根据@markp-fuso):
awk '
/actual/ { n = split($3,a,"") }
/error/ { split($3,e,"") }
END {
for (i = 1; i<=n; ++i)
o = (o) ( e[i]==1 ? "X" : a[i] )
print "output :", o
}
' gpbat
Run Code Online (Sandbox Code Playgroud)
并且,如果保证输入的顺序,则可以在读取“错误”行后停止处理,因此操作可以与 an 一起END移动到操作中,以避免必须读取文件的其余部分:/error/exit
awk '
/actual/ { n = split($3,a,"") }
/error/ {
split($3,e,"")
for (i = 1; i<=n; ++i)
o = (o) ( e[i]==1 ? "X" : a[i] )
print "output :", o
exit
}
' gpbat
Run Code Online (Sandbox Code Playgroud)