引用符内の特定の文字を置き換える

引用符内の特定の文字を置き換える

ログファイルからいくつかの機密データをマスクしようとしています。

まず、一致するパターンを使用してファイル内の特定の行をフィルタリングする必要があります。その後、特定の行に対して二重引用符内のテキストを置き換え、二重引用符内にないテキストを保持する必要があります。

ファイル内のパターン(二重引用符を含む)に一致するすべての行と二重引用符内のすべての内容は、Xに変わるAZ、xに変わるaz、数字0から9を0に置き換える必要があります。

1行に複数の引用符付き文字列を使用できます。内部引用符は、「、」、「-」、「.」、「@」などの特殊文字である可能性があり、これらの文字はそのままにしてください。

サンプルファイルの内容(この例のフィルタワードは「KEYWORD」です):

2020-04-18 15:01:12 [EVENT] :log-event-with-KEYWORD: {:entry1 {:entry2 {:value "Replace This"}}} -> {:entry1 {:entry2 {:value "Replace ALSO this."}}}
2020-04-18 15:01:13 [EVENT] :log-event-with-KEYWORD: {:entry1 {:entry2 {:value "REplace. THIS 12345"}}}
2020-04-18 15:01:15 [EVENT] :this_has--the-KEYWORD: {:entry1 {:entry2 {:value "[email protected]"}}} -> {:entry1 {:entry2 {:value "[email protected]"}}}
2020-04-18 15:01:18 [EVENT] :log-event-without-keyword: {:entry1 {:entry2 {:value "Do NOT replace this."}}} -> {:entry1 {:entry2 {:value "Do-NoT replace this either"}}}

このファイルは入力として次の出力として扱われます。

2020-04-18 15:01:12 [EVENT] :log-event-with-KEYWORD: {:entry1 {:entry2 {:value "Xxxxxxx Xxxx"}}} -> {:entry1 {:entry2 {:value "Xxxxxxx XXXX xxxx."}}}
2020-04-18 15:01:13 [EVENT] :log-event-with-KEYWORD: {:entry1 {:entry2 {:value "XXxxxxx. XXXX 00000"}}}
2020-04-18 15:01:15 [EVENT] :this_has--the-KEYWORD: {:entry1 {:entry2 {:value "[email protected]"}}} -> {:entry1 {:entry2 {:value "[email protected]"}}}
2020-04-18 15:01:18 [EVENT] :log-event-without-keyword: {:entry1 {:entry2 {:value "Do NOT replace this."}}} -> {:entry1 {:entry2 {:value "Do-NoT replace this either"}}}

変更された行はファイル内で更新する必要があり、変更されたファイル全体は標準出力(キーワード、行順序などのないファイルも含む)として処理する必要があります。詳細は保存する必要があります。

grepやsedなどのbashスクリプト/コマンドラインツールを使用してこれを実行できますか?

答え1

awk '/KEYWORD/{
    n=split($0,a,"\"")
    for(i=2;i<=n;i=i+2){
        gsub(/[A-Z]/,"X",a[i])
        gsub(/[a-z]/,"x",a[i])
        gsub(/[0-9]/,"0",a[i])
    }
    sep=""
    for (i=1;i<=n;i++){
        printf "%s%s",sep,a[i]
        sep="\""
    }
    printf "\n"
    next
}
1' file

たとえば、更新された入力ファイルから

2020-04-18 15:01:12 [EVENT] :log-event-with-KEYWORD: {:entry1 {:entry2 {:value "Replace This"}}} -> {:entry1 {:entry2 {:value "Replace ALSO this."}}}
2020-04-18 15:01:13 [EVENT] :log-event-with-KEYWORD: {:entry1 {:entry2 {:value "REplace. THIS 12345"}}}
2020-04-18 15:01:15 [EVENT] :this_has--the-KEYWORD: {:entry1 {:entry2 {:value "[email protected]"}}} -> {:entry1 {:entry2 {:value "[email protected]"}}}
2020-04-18 15:01:18 [EVENT] :log-event-without-keyword: {:entry1 {:entry2 {:value "Do NOT replace this."}}} -> {:entry1 {:entry2 {:value "Do-NoT replace this either"}}}

この awk は所望の出力を生成します。

2020-04-18 15:01:12 [EVENT] :log-event-with-KEYWORD: {:entry1 {:entry2 {:value "Xxxxxxx Xxxx"}}} -> {:entry1 {:entry2 {:value "Xxxxxxx XXXX xxxx."}}}
2020-04-18 15:01:13 [EVENT] :log-event-with-KEYWORD: {:entry1 {:entry2 {:value "XXxxxxx. XXXX 00000"}}}
2020-04-18 15:01:15 [EVENT] :this_has--the-KEYWORD: {:entry1 {:entry2 {:value "[email protected]"}}} -> {:entry1 {:entry2 {:value "[email protected]"}}}
2020-04-18 15:01:18 [EVENT] :log-event-without-keyword: {:entry1 {:entry2 {:value "Do NOT replace this."}}} -> {:entry1 {:entry2 {:value "Do-NoT replace this either"}}}

答え2

使用sed:

sed -E '/KEYWORD/{
        :lower s/("[^"]*)[a-z]([^"]*")/\1_\2/; t lower;
        :upper s/("[^"]*)[A-Z]([^"]*")/\1-\2/; t upper;
        :digit s/("[^"]*)[0-9]([^"]*")/\1*\2/; t digit;
}; y/*_-/0xX/' infile

/KEYWORD/{...}ブロックのコードセットは、行が文字列と一致する場合にのみ実行されますKEYWORD

これは、最初の小文字/大文字/数字が見つかるまで("[^"]*)[###]([^"]*")a以降のすべての項目と一致し、他の引用符が一致するまですべての文字が渡されます。"[a-z][A-Z][0-9]

各部分は、すべての文字が小文字_、大文字-、数字で*ノートx:これらの文字がファイルに表示される場合は、別の文字を選択してください。理由は、またはに直接変更しなかったためですX0使用後はsedが無限に繰り返されるためです。sed ループすべての小/大/数字を置き換えます。

完了すると、その文字は*_-に変換されます0xX

-i入力ファイルの変更を更新するには、上記のコマンドにオプションを追加してくださいsed -i -E ...


修正する:問題を修正するコマンド:

sed -E '/KEYWORD/{
        :lower s/^(([^"]*("[^"]*"){0,1})*)("[^"]*)[a-z]([^"]*")/\1\4_\5/; t lower;
        :upper s/^(([^"]*("[^"]*"){0,1})*)("[^"]*)[A-Z]([^"]*")/\1\4+\5/; t upper;
        :digit s/^(([^"]*("[^"]*"){0,1})*)("[^"]*)[0-9]([^"]*")/\1\4*\5/; t digit;
}; y/*_+/0xX/' infile

答え3

使用真珠:

$ perl -ne 'if ( $_ =~ /KEYWORD/){
  ($first,$matched,$last) = ($1,$2,$3) if ( $_ =~ /^(.*)?\"(.*)\"(.*)$/ );
  $matched =~ tr/[a-z]/x/;$matched =~ tr/[A-Z]/X/;$matched =~ tr/0-9/0/;
  print $first."\"".$matched."\"".$last."\n";
  }
  else { print }' <<inputFile>>

編集する:パターンが複数回表示される場合。次は動作します。

$ perl -ne ' {
  if ( $_ =~ /KEYWORD/ ){
  $line=$_;$val=1;
  while($val) {
  ($first,$matched,$last) =  ($1,$2,$3) if ( $line =~ m/(.*?)\"(.*?)\"(.*)$/ );
  $val =  $line =~ s/\".*?\"/_/;
  $matched =~ tr/[a-z]/x/;$matched =~ tr/[A-Z]/X/;$matched =~ tr/0-9/0/;
  $matched = "_".$matched."_";
  $line=$first.$matched.$last;
  }
  $line =~ s/[_]*_/"/g;
  print "$line\n";
  }else { print } }' <<inputFile>>

関連情報