テキストを置き換える最良の方法

テキストを置き換える最良の方法

私のファイルには次のテキストがあります

/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ではゼロ以外の方が多いですMD5 sum。)IGNORECASE

別の問題は順列の数です。これらをすべてプログラムで一致させることは非現実的です。

コードは次のように動作します。

  • は文字位置で、リテラル文字であるdesc[]インデックスを使用してメッセージ配列を作成します。"XY"XY
  • XYYはX番目の位置にある " "から " "にインデックスを変換します...Y.....(もちろん直接実行することもできますが、退屈でエラーが発生しやすい)。
  • 各入力ラインを読み、各インデックスパターンを順番に一致させ、関連するメッセージを蓄積します。output[]
  • output[]カンマ区切りリストでフラット化
  • 各入力ラインの結果を印刷します。

慣れていない場合は、(expression) ? "true" : "false"ここでこの構造を使用して、カンマまたは複数形の末尾の「s」(該当する場合)を挿入(または挿入しない)し、保存してif/elseコピーします。はマジックナンバー文字列、9はマジックナンバーです(出力が実際に古く、列9に「P」がない場合は"........."変更できます)。rpm

" "を使用すると、各側面のパディングの可変長プレフィックスを%.*s選択できます。位置N(1から始まる)の場合、N-1文字を接頭辞に出力し、一致する部分を出力し、9-N文字を接尾辞に出力します。printf()"........."

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スクリプトでした。照会用にハードコードされた月名の配列があります。月の名前がありません。。これを見つけるのにどれくらいの時間がかかるのか驚かれるでしょう。

おすすめ記事