다음과 같은 파일이 있습니다(list_20.txt).
[{"d_prime":"0.475425","variation1":"rs909776","r2":"0.057940","variation2":"rs16991816","population_name":"1000GENOMES:phase_3:KHV"}]
[{"r2":"0.057940","variation1":"rs909776","d_prime":"0.475425","population_name":"1000GENOMES:phase_3:KHV","variation2":"rs16991819"}]
[{"variation1":"rs909776","r2":"0.078476","d_prime":"0.546491","population_name":"1000GENOMES:phase_3:KHV","variation2":"rs8114269"}]
[{"population_name":"1000GENOMES:phase_3:KHV","variation2":"rs8114269","r2":"0.073418","variation1":"rs6130034","d_prime":"0.528588"}]
[{"population_name":"1000GENOMES:phase_3:KHV","variation2":"rs1201686","r2":"0.060239","variation1":"rs3746539","d_prime":"0.271891"}]
[{"variation2":"rs1201686","population_name":"1000GENOMES:phase_3:KHV","d_prime":"0.280262","r2":"0.058212","variation1":"rs2144011"}]
[{"population_name":"1000GENOMES:phase_3:KHV","variation2":"rs10485662","r2":"0.058826","variation1":"rs844808","d_prime":"0.423639"}]
[{"variation2":"rs6065565","population_name":"1000GENOMES:phase_3:KHV","d_prime":"0.638509","r2":"0.110749","variation1":"rs6139746"}]
[{"r2":"0.110749","variation1":"rs6139746","d_prime":"0.638509","population_name":"1000GENOMES:phase_3:KHV","variation2":"rs6072936"}]
[{"population_name":"1000GENOMES:phase_3:KHV","variation2":"rs6065562","variation1":"rs6139746","r2":"0.091021","d_prime":"0.606214"}]
[{"variation1":"rs6139746","r2":"0.910749","d_prime":"0.638509","population_name":"1000GENOMES:phase_3:KHV","variation2":"rs6072937"}]
...
"r2":" 뒤에 값이 0.7보다 크고 1보다 작거나 같은 행만 추출하고 싶습니다.
이 예에서 예상되는 출력은 다음 줄입니다.
[{"variation1":"rs6139746","r2":"0.910749","d_prime":"0.638509","population_name":"1000GENOMES:phase_3:KHV","variation2":"rs6072937"}]
나는 이것을 시도했습니다 :
awk '$NF >= 0.8 && $NF <1 {print $0}' list_20.txt > 20.out
하지만 빈 파일을 얻습니다. 게다가 이 명령은 관심 문자열 "r2"에만 국한되지 않습니다:"
답변1
이는 JSON과 유사하므로 명령줄 JSON 구문 분석기를 사용합니다.
$ jq '.[] | select((.r2|tonumber) > 0.7 and (.r2|tonumber) <= 1)' file
{
"variation1": "rs6139746",
"r2": "0.910749",
"d_prime": "0.638509",
"population_name": "1000GENOMES:phase_3:KHV",
"variation2": "rs6072937"
}
r2
키 값을 문자열에서 올바른 숫자로 변환하는 데 사용해야 tonumber
하지만 그 외에는 단순한 필터입니다 select()
.
약간 단축하거나 최소한 각 숫자를 변환하는 것을 피할 수 있습니다.두 배, 그리고
jq '.[] | (.r2|tonumber) as $r2 | select($r2 > 0.7 and $r2 <= 1)' file
결과가 입력과 동일한 형식이기를 원하면 다음을 사용하십시오.
$ jq -c '.[] | (.r2|tonumber) as $r2 | select($r2 > 0.7 and $r2 <= 1) | [.]' file
[{"variation1":"rs6139746","r2":"0.910749","d_prime":"0.638509","population_name":"1000GENOMES:phase_3:KHV","variation2":"rs6072937"}]
즉, "컴팩트한 출력"을 요청하고 -c
필터를 통해 추출된 각 결과에 대한 배열을 생성하는 데 사용합니다.select()
[.]
답변2
awk를 사용하세요:
awk 'match($0, /"r2":"[^"]+"/) {
t = substr($0, RSTART+6, RLENGTH-7)
f = 0.7<t+0 && t+0<=1
if ( f ) print
}' list_20.txt
Perl에서도 이 작업을 수행할 수 있습니다.
perl -lne '
print if /"r2":"(.*?)"/ and 0.7<$1 && $1<=1;
' list_20.txt
우리는 따옴표로 묶인 문자열 r2와 그 뒤에 오는 내용을 찾고 있습니다. 그런 다음 범위 확인 조건을 적용하고 범위 내에 있는 것으로 확인되면 해당 행을 인쇄합니다.
답변3
awk -F'[][{},]' '{
for (i=3;i<=NF-2;i++){
if ($i ~ /^"r2"/){
r2=substr($i, 7, length($i)-7)
if (r2>0.7 && r2<=1){ print; break }
}
}
}' list_20.txt > 20.out
]
, [
및 {
를 필드 구분 기호 }
로 사용합니다 . ,
그런 다음 처음 두 필드와 마지막 두 필드를 건너뛰면서 각 레코드의 필드를 반복합니다(항상 비어 있으므로).
현재 필드가 값으로 시작하는지 테스트하고 "r2"
해당 값을 추출합니다 substr($i, 7, length($i)-7)
. 즉, 처음 6자를 건너뛰고 "r2":"
마지막 문자를 생략합니다 "
.
값이 범위 내에 있으면 레코드를 인쇄하고 루프를 중단합니다.
답변4
숫자가 부동 소수점인 경우 다음과 같이 줄을 정리할 수 있습니다.
$ LC_ALL=C grep -E '"r2":"((0?\.(7[0-9]*[1-9][0-9]*|[89][0-9]*))|1(\.0*)?)"' list_20.txt
-E
확장 정규식을 활성화하는 옵션