특정 문자열 뒤의 숫자가 임계값보다 큰 행을 구문 분석하는 방법은 무엇입니까?

특정 문자열 뒤의 숫자가 임계값보다 큰 행을 구문 분석하는 방법은 무엇입니까?

다음과 같은 파일이 있습니다(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 확장 정규식을 활성화하는 옵션

관련 정보