따옴표 안의 특정 문자 바꾸기

따옴표 안의 특정 문자 바꾸기

로그 파일에서 일부 민감한 데이터를 마스킹하려고 합니다.

먼저 일치하는 패턴을 사용하여 파일에서 특정 줄을 필터링해야 합니다. 그런 다음 해당 특정 줄에 대해 큰따옴표 안에 있는 텍스트를 바꾸고 큰따옴표 안에 있지 않은 텍스트는 유지해야 합니다.

파일에서 패턴(큰따옴표 포함)과 일치하는 모든 줄과 큰따옴표 안의 모든 내용은 X로 바뀌는 AZ, x로 바뀌는 az, 숫자 0-9를 0으로 바꿔야 합니다.

한 줄에 여러 개의 인용 문자열을 사용할 수 있습니다. 내부 따옴표는 ",", "-", ".", "@"와 같은 특수 문자일 수도 있으며 이러한 문자는 그대로 두어야 합니다.

샘플 파일 콘텐츠(이 예의 필터 단어는 "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: 이러한 문자가 파일에 나타날 수 있는 경우 다른 문자를 선택하십시오. 이유는 또는 으로 직접 바꾸지 않았기 때문입니다 X. 0사용 후 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>>

관련 정보