替换文本的最佳方法

替换文本的最佳方法

我的文件中有以下文本

/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)循环中的匹配来处理这个问题。


  1. 我修复的第一个脚本错误是处理日志文件的 awk 脚本。它有一个用于查找的硬编码的月份名称数组,或者更确切地说是一个数组一个月名字缺失。你会惊讶地发现要花多长时间才能发现这一点......

相关内容