다음 예와 같은 줄이 포함된 JSON 형식의 대용량 로그 파일이 있습니다.
{"data_1":210,"target_number":1096748811,"extra_data":66}
{"data_1":0,"target_number":7130881445,"extra_data":56}
{"data_1":1712,"target_number":1098334917,"extra_data":48}
{"data_1":0,"target_number":3062674667,"extra_data":54}
{"data_1":53,"target_number":5110609228,"extra_data":246}
target_number
값을 전체 파일의 MD5 해시로 바꾸고 싶습니다 .
sed
다음 기본 구문을 사용하여 명령을 시도하고 있습니다 .
sed -i 's/target_number/target_number_md5/' input.log
위 예의 첫 번째 항목에 대한 예상 출력은 다음과 같습니다.
{"data_1":210,"target_number":620e25e6f054992308c564cb883e4940,"extra_data":66}
답변1
다음 명령을 사용하십시오밀러( ) JSON 입력을 구문 분석합니다("JSON 라인"을 읽으 려면 mlr
Miller 버전 6 이상을 사용해야 함 ). 그런 다음 하위 명령을 사용하여 키 값을 수정합니다 . 수정은 표준 입력에 전달된 원래 값을 호출하여 수행됩니다. 그런 다음 응답에서 MD5 해시를 제외한 모든 항목을 제거하여 결과 문자열을 삭제합니다.--jsonl
--json
put
target_number
openssl md5
mlr --json put '
$target_number = system("printf \"" . $target_number . "\" | openssl md5");
$target_number = sub($target_number, ".*= ", "")' file
md5sum
GNU coreutils를 사용하려면 openssl md5
위의 내용을 md5sum --tag
.
md5
유틸리티(일반적으로 BSD 시스템에서 발견됨)를 사용하면 printf
파이프를 피할 수 있습니다.
mlr --json put '
$target_number = system("md5 -s \"" . $target_number . "\"");
$target_number = sub($target_number, ".*= ", "")' file
질문의 예에서 위 명령 각각의 출력은 다음과 같습니다.
{ "data_1": 210, "target_number": "620e25e6f054992308c564cb883e4940", "extra_data": 66 }
{ "data_1": 0, "target_number": "f83d74be3dcb71d53263aefdf08203a9", "extra_data": 56 }
{ "data_1": 1712, "target_number": "56ae797ad2c16813d1a6168d28b58d89", "extra_data": 48 }
{ "data_1": 0, "target_number": "81394a193503036fad53b8a9d6ca2456", "extra_data": 54 }
{ "data_1": 53, "target_number": "6f01490a5dc694e51a69b79f7dd21c24", "extra_data": 246 }
MD5 해시는 십진수가 아닌 문자열이므로 생성된 JSON 문서에 문자열로 삽입됩니다.
mlr
해당 옵션을 사용하면 Miller는 입력 파일을 생성된 문서로 바꿀 수 있습니다(즉, "제자리에서" 편집) -I
.
target_number
위의 각 명령은 호출 시 원시 값을 system()
삭제하지 않고 사용하므로, 그렇게 하면 코드 주입 취약점이 발생합니다.
답변2
비슷한 문제를 해결하면서 이 질문을 찾았습니다. 루프 없이 해결하고 싶기 때문에 제공된 솔루션이 나에게 적합하지 않습니다.
루프 없이 문제를 해결하는 방법에 대한 개념 증명은 다음과 같습니다.
sed -E 's/(.*target_number":)([0-9]+)(.*)/echo "\1$(echo -n \2 | md5sum)\3"/e;s/ -//' "$inputFile"
-E
: 기본 정규식 대신 확장 정규식을 사용하세요./e
: 이 명령을 사용하면 쉘 명령 입력을 패턴 공간으로 파이프할 수 있습니다.
자세한 내용은 다음 소스를 확인하세요.https://www.gnu.org/software/sed/manual/sed.html
답변3
나는 스스로 답을 찾았습니다.
cat $inputFile | grep -Po '(?<="target_number":)[^,"]+' | while read i ; do
sed -i "s/$i/$(echo -n $i | md5sum | cut -f 1 -d ' ')/g" $outputFile
done