내 사용법은 다음과 같습니다.
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
직렬화된 객체는 @json
in 연산자를 사용하여 생성될 수 있으며 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 정렬이 없다면 매우 간단한 해결 방법이 있으므로 알려주십시오.