필드에서 길이 n의 숫자를 추출하고 문자열을 반환합니다.

필드에서 길이 n의 숫자를 추출하고 문자열을 반환합니다.

텍스트와 숫자의 조합이 포함된 탭으로 구분된 파일이 있습니다. 각 행은 그대로 유지하고 싶지만 다섯 번째 열에는 6자리 숫자만 존재한다면 그대로 유지하고 싶습니다. 예를 들어:

gene1   NM_033629   598G>A  P912    syndrome  1, 192315 syndrome 2,  225750 syndrome 3 610448   score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   syndrome 1 600195   score   AD  rec user    234567  Source

(증후군 #은 예시로 사용되었으며 임의의 텍스트일 수 있으므로 검색하고 삭제할 수 있는 패턴은 아닙니다.)

나는 출력을 다음과 같이 원한다:

gene1   NM_033629   598G>A  P912    192315 225750 610448    score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   600195  score   AD  rec user    234567  Source

6자리 숫자를 추출하는 방법에는 4가지가 있지만 그럴 수 없습니다.

ㅏ. 원래 행의 숫자를 출력합니다.

b. 편집된 필드가 포함된 전체 줄을 성공적으로 인쇄합니다. 숫자를 추출하는 데 사용하는 옵션은 다음과 같습니다.

cat inputfile | cut -f 5 |grep -P '(? < !\d)\d{6}(?!\d)'
cat inputfile | cut -f 5 |grep -Po '(?< !\d)\d{6}(?!\d)'
cat inputfile | cut -f 5 |grep -o '[[:digit:]]*'
cat inputfile | cut -f 5 |grep -o "[0-9]\{6\}"

열에 cut을 사용하는 것이 올바르지 않다는 것을 알고 있지만 필드 9에도 6자리 숫자가 있으므로 추출이 올바른지 확인하고 싶습니다. 나는 그것을 모두 함께 유지한다고 주장합니다. 어떤 제안이라도 미리 감사드립니다.

답변1

내가 올바르게 이해했다면 다섯 번째 열은 그 안에 있는 6자리 숫자를 모두 공백으로 연결하기를 원할 것입니다.

아마도:

perl -F'\t' -lape '
   $F[4] = join " ", grep {length == 6} ($F[4] =~ /\d+/g);
   $_ = join "\t", @F' < file

또는 운영자에 대한 부정적인 의견을 재사용하십시오.

perl -F'\t' -lape '
   $F[4] = join " ", ($F[4] =~ /(?<!\d)\d{6}(?!\d)/g);
   $_ = join "\t", @F' < file

그리고 awk:

awk -F'\t' -v OFS='\t' '
  {
    repl = sep = ""
    while (match($5, /[0-9]+/)) {
      if (RLENGTH == 6) {
        repl = repl sep substr($5, RSTART, RLENGTH)
        sep = " "
      }
      $5 = substr($5, RSTART+RLENGTH)
    }
    $5 = repl
    print
  }' < file

grep그 자체로는 작업에 충분하지 않습니다. grep패턴과 일치하는 선을 인쇄하도록 설계되었습니다. GNU 또는 ast-open과 같은 일부 구현은 일치하는 줄에서 문자열을 추출 grep할 수 있지만 pcregrep이는 매우 제한적입니다.

특정 제한 사항에서 작동할 수 있다고 생각되는 유일한 ++ 접근 방식은 다음을 cut구현하는 것입니다.greppastepcregrep grep

n='(?:.*?((?1)))?'
paste <(< file cut -f1-4) <(< file cut -f5 |
  pcregrep --om-separator=" " -o1 -o2 -o3 -o4 -o5 -o6 -o7 -o8 -o9 \
    "((?<!\d)\d{6}(?!\d))$n$n$n$n$n$n$n$n"
  ) <(< file cut -f6-)

각 입력 줄에는 최소 6개의 필드가 있고 각 필드의 5번째 필드에는 1~9개의 6자리 숫자가 있다고 가정합니다.

답변2

awk '
BEGIN {
    FS = "\t";
    OFS = "\t";
}
{
    cnt = patsplit($5, arr, /[0-9]{6}/);
    $5 = arr[1];
    for(i = 2; i <= cnt; i++) {
        $5 = $5 " " arr[i];
    }
    print;
}' input.txt

patsplit(s, a [, r [, seps] ])- 분할 문자열 에스배열로및 구분자 배열9월정규 표현식에 대해아르 자형, 필드 수를 반환합니다. 요소 값은 r과 일치하는 s의 일부입니다..

입력하다:

gene1   NM_033629   598G>A  P912    syndrome 1, 192315 syndrome 2, 225750 syndrome 3 610448 score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   syndrome 1 600195   score   AD  rec user    234567  Source

산출:

gene1   NM_033629   598G>A  P912    192315 225750 610448    score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   600195  score   AD  rec user    234567  Source

관련 정보