디렉터리의 여러 텍스트 파일에서 특정 문자열 뒤의 모든 텍스트를 제거합니다.

디렉터리의 여러 텍스트 파일에서 특정 문자열 뒤의 모든 텍스트를 제거합니다.

검증하고 확인해야 할 약 25,000개의 JSON 파일이 있는데, Excel을 사용하여 JSON을 CSV로 변환할 때 일부 파일이 중복되어 오류가 발생하는 것을 발견했습니다.

그 이후의 모든 문자열을 제거하려고 합니다. "version":"0.2.3"}이는 반복되기 전에 JSON의 끝을 나타내기 때문입니다. "version": "0.2.3"}{"analysis": {따라서 그 이후의 모든 항목을 유지 "version": "0.2.3"}하고 제거 하고 해당 변경 사항을 25,000개 파일 모두에 적용해야 합니다. {"analysis": {사람들이 grep과 sed를 사용하는 것을 본 적이 있지만 직접 작동하게 할 수는 없는 것 같습니다.

누군가 도움을 줄 수 있다면 감사하겠습니다. 텍스트를 수동으로 삭제하는 것은 바람직하지 않으므로 bash 등에 라이너가 있기를 바랍니다!

아래는 수정해야 할 사항(파일 중 하나의 제거된 버전)이고 아래는 원하는 출력입니다. 보시다시피, 어떤 이유로든 API 사용 중에 JSON 데이터가 자체적으로 복사될 수 있습니다.

문제가 있는 입력(잘림 json):

{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}

원하는 출력:

{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}

답변1

(대부분의 Unix 계열 시스템에서 작동) 을 사용하면 jq파일에서 첫 번째 JSON 객체를 추출하고 다음을 사용하여 나머지를 버릴 수 있습니다.

jq -n 'input' file >newfile

이렇게 하면 "예쁜 인쇄" JSON이 생성됩니다. -c"간소한" 출력(공백이 최소화된 단일 행)을 얻으려면 이 옵션을 사용하십시오 . 출력은 에 기록됩니다 newfile.

jq지시문은 input사용 가능한 다음 JSON 개체를 생성합니다. -n( )를 사용하여 --null-input기본 데이터 읽기를 끄고 input입력 파일의 첫 번째 개체만 처리합니다.

질문에 제공된 데이터에 대해 이는 다음을 산출합니다.

{
  "analysis": {
    "score": 3
  },
  "sample": {
    "completed": "2022-01-27T21:22:21Z",
    "created": "2022-01-27T21:17:57Z",
    "id": "220127-z5h84saffl",
    "md5": "7871a75734af389b787bad57a3ea087d",
    "score": 3,
    "sha1": "58a8689ee76a46559ea56a52d20425f44c8ff601",
    "sha256": "23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"
  },
  "version": "0.2.3"
}

그런 다음 원본 파일을 결과로 덮어쓰면 됩니다. 단일 파일의 전체 처리는 다음과 같습니다.

jq -n 'input' file >newfile &&
mv newfile file

파일이 현재 디렉터리에 있고 특정 패턴과 일치한다고 가정하면 *.json다음과 같이 간단한 셸 루프에서 모든 파일을 처리할 수 있습니다.

for name in *.json; do
    cp -- "$name" "$name.orig" &&
    jq -n 'input' <"$name.orig" >"$name"
done

이것은 제가 방금 보여드린 것과는 약간 다르며, 원본 콘텐츠를 .orig파일 이름 접미사를 사용하여 파일에 유지하고 원본 파일의 메타데이터(권한 등)가 변경되지 않도록 합니다. 이 작업을 올바르게 수행했다고 확신하면 .orig파일 이름 접미사가 붙은 파일을 삭제할 수 있습니다.

항상 적절하게 백업된 데이터에 대해 이러한 테스트를 수행하십시오.


또한 이러한 파일을 CSV로 변환한다고 언급했지만 무엇이 필요한지는 언급하지 않았습니다. sample키를 헤더로 사용하여 데이터를 CSV 형식으로 만들고 싶다고 가정해 보겠습니다 .

jq -n -r 'input | .sample | keys, [.[]] | @csv' file

JSON 문자열 대신 디코딩된 데이터를 제공하려면 Option()이 필요합니다 -r.--raw-output

특정 문서에 대해 다음을 제공합니다.

"completed","created","id","md5","score","sha1","sha256"
"2022-01-27T21:22:21Z","2022-01-27T21:17:57Z","220127-z5h84saffl","7871a75734af389b787bad57a3ea087d",3,"58a8689ee76a46559ea56a52d20425f44c8ff601","23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"

답변2

사용행복하다(이전 Perl_6)

입력 예(잘못된 JSON):

~$ cat file.json
{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}

출력 예(Raku의 해시 형식):

~$ cat file.json | raku -MJSON::Stream -e 'my @a;  \
   react whenever json-stream($*IN.Supply, [q[$], *][0],) {@a.push($_.values)};  \
   "\n".print; .say for @a.[0].hash;'

sample => {completed => 2022-01-27T21:22:21Z, created => 2022-01-27T21:17:57Z, id => 220127-z5h84saffl, md5 => 7871a75734af389b787bad57a3ea087d, score => 3, sha1 => 58a8689ee76a46559ea56a52d20425f44c8ff601, sha256 => 23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a}
version => 0.2.3
analysis => {score => 3}

위에서는 Raku의 모듈을 사용하여 불완전한 JSON을 읽을 수 있습니다 JSON::Stream. 이는 JSON 스트림 파서(EOF에 도달하기 전에 구문 분석)이므로 JSON의 유효성을 검사하지 않기 때문입니다. 이 경우에는 운이 좋았습니다. 배열에서 잘못된 두 번째 요소를 제거하려면 호출을 사용하십시오 @a.[0].hash( @a.head.hash또한 작동함).


최종 형식 출력은 Raku 모듈의 명령을 JSON사용하여 수행 됩니다. 전체적으로 우리가 한 일은 다음과 같습니다.to-json()JSON::Tiny

최종 JSON 출력(Raku 모듈만 사용):

~$ cat Jarvis4444.json | raku -MJSON::Stream -MJSON::Tiny -e 'my @a;  \
   react whenever json-stream($*IN.Supply, [q[$], *][0],) {@a.push($_.values)};  \
   "\n".print; to-json(@a.[0].hash).put;'

{ "version" : "0.2.3", "sample" : { "score" : 3, "created" : "2022-01-27T21:17:57Z", "sha1" : "58a8689ee76a46559ea56a52d20425f44c8ff601", "id" : "220127-z5h84saffl", "sha256" : "23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a", "md5" : "7871a75734af389b787bad57a3ea087d", "completed" : "2022-01-27T21:22:21Z" }, "analysis" : { "score" : 3 } }

다른 답변과 비교하기 위해 위의 JSON 출력을 |파이프할 수 있습니다 jq.

{
  "sample": {
    "completed": "2022-01-27T21:22:21Z",
    "score": 3,
    "sha1": "58a8689ee76a46559ea56a52d20425f44c8ff601",
    "md5": "7871a75734af389b787bad57a3ea087d",
    "id": "220127-z5h84saffl",
    "sha256": "23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a",
    "created": "2022-01-27T21:17:57Z"
  },
  "version": "0.2.3",
  "analysis": {
    "score": 3
  }
}

[여러 파일 처리: 물론 @Kusalananda의 답변은 여러 파일을 처리하기 위한 쉘 루프 작성, 각 파일 수정/저장에 대한 충분한 지침을 제공합니다.]

https://github.com/moritz/json
https://github.com/FCO/JSON-Stream
https://raku.org

관련 정보