我的文件中有以下文本
/etc/pam.d/systemd-user|S.5....T.
/etc/bluetooth|not owned
/etc/pam.d/crond|S.5....T.
/etc/pam.d/crond|S.5....T.
/var/log/dmesg|.M.......
之后的文本|
将更改为全部.
或将具有以下内容的混合或全部SM5DLUGT
我想用它代替一些更易于理解的示例
.M......=Mode differs includes permissions and file type
SM......=Filesize,Mode differs includes permissions and file type
..5.....=md5 sum differs
每个的细分.
如下
S file Size differs
M Mode differs (includes permissions and file type)
5 MD5 sum differs
D Device major/minor number mismatch
L readLink(2) path mismatch
U User ownership differs
G Group ownership differs
T mTime differs
我想在 awk 中做类似下面的事情
awk '{sub(/S......./,"file size differs")}; {sub(/SM....../,"file size\
differs,mode differes includes permissions and file type")}; \
{sub(/.M....../,"Mode differes includes permissions and file type")}; \
{sub(/..5...../,"MD5 sum differes differs")}; \
{sub(/...D..../,"Devicemajor/minoir number mistmatch")}; \
{sub(/....L.../,"Readlink path mismatch")}; \
{sub(/.....U../,"User ownership differs")}; \
{sub(/......G./,"file size differs")}; {sub(/.......T/,"mTime differs")}; \
{print $0}' /system_files_protection.txt
答案1
我假设您正在解析验证模式下的输出rpm
,因此已经进行了一些细微的调整(尽管我不确定“不拥有”行)。支持处理“?”对于失败的测试不是不过也包括在这里。
您的方法的主要问题是,人们(通常)不应尝试在修改数据时增量处理数据;然后 ”。”在您匹配的字符串中是一个正则表达式通配符,它可以匹配修改后的数据。例如,/.M......./
作为正则表达式将匹配“ .M.......
”、“ Mode differs
”、“ ”等(如果在 GNU awk 中不为 0,MD5 sum
则更多。)IGNORECASE
另一个问题是排列的数量,以编程方式将它们全部匹配是不切实际的。
该代码的工作原理如下:
- 创建一个消息数组
desc[]
,索引为"XY"
whereX
是字符位置,Y
是文字字符 - 将索引从“
XY
”转换为“...Y.....
”,其中 Y 位于第 X 个位置(当然,您可以自己执行此操作,但这很乏味且容易出错) - 读取每个输入行,尝试依次匹配每个索引模式,并将相关消息累积在
output[]
- 展平
output[]
为逗号分隔的列表 - 打印每个输入行的结果
如果您不熟悉,(expression) ? "true" : "false"
这里使用该结构插入(或不插入)逗号或复数尾随“s”(如果适用)、保存if/else
和复制。是一个幻数字符串,9 是一个幻数(如果您的输出确实很旧并且缺少“P”作为第 9 列,"........."
您可以更改这些)。rpm
中的“ %.*s
”允许选择每侧填充printf()
的可变长度前缀。"........."
对于位置 N(从 1 开始),它输出 N-1 个字符到前缀、匹配部分,然后输出 9-N 个字符到后缀。
BEGIN {
FS="|"
desc["1S"]="file Size differs"
desc["2M"]="Mode differs (includes permissions and file type)"
desc["35"]="MD5 sum differs"
desc["4D"]="Device major/minor number mismatch"
desc["5L"]="readLink(2) path mismatch"
desc["6U"]="User ownership differs"
desc["7G"]="Group ownership differs"
desc["8T"]="mTime differs"
desc["9P"]="caPabilities differ"
## transform indexes: "4D" -> "...D....." with "D" in the 4th column
for (dd in desc) {
match(dd,/([0-9]+)(.)/,bits)
regex=sprintf("%.*s%s%.*s",bits[1]-1,".........",bits[2],
9-bits[1],"........")
sub(/ differs?/,"",desc[dd])
desc[regex]=desc[dd]; delete desc[dd]
}
}
{
oo=0; out=""
for (regex in desc)
if ($2 ~ regex) output[++oo]=desc[regex]
for (ii=1; ii<=oo; ii++)
out=sprintf("%s%s%s",out, (ii>1)?", ":"", output[ii]);
printf("%s|%s differ%sn",$1,out,(oo==1)?"s":"")
}
这样的代码足够灵活,可以处理像这样的标志的许多变体。
如果您需要处理“?”在输入中,您也可以修改正则表达式代码以生成更复杂的正则表达式,例如“ .(M|\?).......
”而不仅仅是“ .M.......
”;然后通过检查for (regex in desc)
循环中的匹配来处理这个问题。
- 我修复的第一个脚本错误是处理日志文件的 awk 脚本。它有一个用于查找的硬编码的月份名称数组,或者更确切地说是一个数组一个月名字缺失。你会惊讶地发现要花多长时间才能发现这一点......