패턴 검색 및 동일한 이름의 파일 생성

패턴 검색 및 동일한 이름의 파일 생성

내 사용법은 다음과 같습니다.

grep -i '"location_country":"country name"' file.txt >> sample.txt

여러 국가가 포함된 대용량 파일을 검색하고 있는데 국가 이름이 포함된 텍스트 파일을 동적으로 생성하고 동일한 국가의 모든 일치 항목을 해당 파일에 저장하고 싶습니다. 이는 country name.txt모든 항목에 대해 의미합니다.

이 같은

grep -i '"location_country":"(.+)"' file.txt >> \1.txt

데이터의 예:

{"full_name":"name1","location_country":"united kingdom"}
{"full_name":"name2","location_country":"united states"}
{"full_name":"name3","location_country":"china"}

따라서 국가 이름이 포함된 별도의 텍스트 파일 3개를 만들어야 합니다. 예 united kingdom.txt:

{"full_name":"name1","location_country":"united kingdom"}

나는 이미 bash 스크립팅을 사용하고 있으므로 상관하지 않습니다. 어떻게 하면 이를 달성할 수 있습니까? 저는 리눅스 머신을 사용하고 있습니다.

답변1

파일은 일련의 JSON 개체로 구성됩니다. 각 객체에는 .location_country키가 포함되어 있습니다. 각 개체에서 키 값으로 명명된 파일에 개체 자체의 직렬화된 복사본을 쓰는 셸 명령을 만들 수 있습니다 .location_country. 그런 다음 이러한 쉘 명령은 쉘에 의해 실행될 수 있습니다.

,jq

jq -r '"printf \"%s\\n\" \(. | @json | @sh) >\(.location_country|@sh).txt"' file.txt

직렬화된 객체는 @jsonin 연산자를 사용하여 생성될 수 있으며 jq, 이 연산자는 입력 문서(이 경우 현재 객체)가 포함된 JSON 인코딩 문자열을 내보냅니다. 그런 다음 @sh쉘의 문자열을 적절하게 인용하기 위해 공급됩니다. 연산자 @sh는 키 값에서 출력 파일 이름의 일부를 생성하는 데에도 사용됩니다 .location_country.

printf이 명령은 기본적으로 를 호출 하여 현재 개체를 출력하고 출력을 특정 파일로 리디렉션하는 셸 코드를 생성합니다 .

의 예제 데이터가 주어지면 file.txt다음을 내보냅니다.

printf "%s\n" '{"full_name":"name1","location_country":"united kingdom"}' >'united kingdom'.txt
printf "%s\n" '{"full_name":"name2","location_country":"united states"}' >'united states'.txt
printf "%s\n" '{"full_name":"name3","location_country":"china"}' >'china'.txt

이를 별도의 파일로 리디렉션하고 실행하여 명령을 실행하거나 셸에서 직접 sh사용할 수 있습니다 .eval

eval "$( jq ...as above... )"

적절한 JSON 파서인 을 사용하고 있으므로 jq입력 JSON 문서가 한 줄에 단일 개체로 형식화되지 않은 경우에도 위의 내용이 작동합니다.

$ cat file.txt
{
  "full_name": "name1",
  "location_country": "united kingdom"
}
{
  "full_name": "name2",
  "location_country": "united states"
}
{
  "full_name": "name3",
  "location_country": "china"
}
$ jq -r '"printf \"%s\\n\" \(. | @json | @sh) >\(.location_country|@sh).txt"' file.txt
printf "%s\n" '{"full_name":"name1","location_country":"united kingdom"}' >'united kingdom'.txt
printf "%s\n" '{"full_name":"name2","location_country":"united states"}' >'united states'.txt
printf "%s\n" '{"full_name":"name3","location_country":"china"}' >'china'.txt
$ eval "$( jq -r '"printf \"%s\\n\" \(. | @json | @sh) >\(.location_country|@sh).txt"' file.txt )"
$ ls
china.txt           file.txt            united kingdom.txt  united states.txt
$ cat 'united kingdom.txt'
{"full_name":"name1","location_country":"united kingdom"}

답변2

사용awk

입력

$ cat input_file
{"full_name":"name1","location_country":"united kingdom"}
{"full_name":"name2","location_country":"united states"}
{"full_name":"name3","location_country":"china"}
{"full name":"name12","location":"china"}
{"full name":"name11","location":"china"}
awk -F"[\"|:]" '$10~/[A-Za-z]/ {print > $10".txt"}' input_file

산출

$ cat china.txt
{"full_name":"name3","location_country":"china"}
{"full name":"name12","location":"china"}
{"full name":"name11","location":"china"}

$ cat united\ kingdom.txt
{"full_name":"name1","location_country":"united kingdom"}

$ cat united\ states.txt
{"full_name":"name2","location_country":"united states"}

답변3

아래의 의견을 고려하면 match()에 대한 세 번째 인수에 대해 GNU awk를 사용하고 동시에 열려 있는 많은 파일을 처리하기 위해 원하는 작업을 수행해야 합니다.

awk 'match($0,/"location_country":"([^"]+)"/,a) { print > (a[1] ".txt") }' file

실행 속도를 위해서는 장식/정렬/사용/장식 취소 접근 방식이 가장 좋을 것입니다. 예:

awk -v OFS='"' 'match($0,/"location_country":"[^"]+"/) { print substr($0,RSTART+20,RLENGTH-21), $0 }' file |
sort -t'"' -k1,1 |
awk -F'"' '$1!=prev { close(out); out=$1 ".txt"; prev=$1 } { print > out }' |
cut -d'"' -f2-

그리고 그것은 어떤 종류, awk, 컷에서도 작동합니다.


원래 답변:

데이터가 항상 단순/정규적인 경우 필요한 것은 GNU awk를 사용하는 것뿐입니다(동시에 열려 있는 많은 출력 파일을 처리하기 위해).

awk -F'"' '{ print > ($5 ".txt") }' file

또는 이것은 awk와 함께:

awk -F'"' '{
    out = $5 ".txt"
    if ( !seen[out]++ ) {
        printf "" > out
    }
    print >> out
    close(out)
}' file

위의 방법은 출력 파일을 생성하는 데 사용할 수 있는 디스크 공간이 있는 한 입력 파일의 크기에 관계없이 작동합니다.

원하는 경우 국가 이름을 먼저 정렬하면 보다 효율적으로 작업을 수행할 수 있습니다.

sort -t'"' -k5,5 file |
awk -F'"' '$5 != prev{ close(out); out=$5 ".txt"; prev=$5 } { print > out }'

마지막 스크립트는 모든 종류와 모든 종류에서 작동하지만 각 국가에 대한 입력 줄의 순서를 재정렬할 수 있습니다. 그것에 관심이 있고 GNU 정렬이 있으면 -s인수를 추가하십시오. 관심이 있고 GNU 정렬이 없다면 매우 간단한 해결 방법이 있으므로 알려주십시오.

관련 정보