나는 의료 유전학 분야에서 일하고 있으며 종종 열 중 하나(예: 열 5)에 텍스트 문자열이 있는 구분된 텍스트 파일을 가지고 있습니다. 우리 전문 용어로는 "돌연변이" 입니다
c.2458C>T
.
c.45_46delAA
c.749_754delinsTG
마찬가지로 다른 파일에서는 다음과 같이 읽을 수 있습니다.
p.Glu34*
또는 p.Ala78_Arg80del
또는p.L378Ffs*11
및 이 있어야 하지만 생략될 수도 있습니다 c.
. p.
숫자가 아닌 문자는 얼마든지 있을 수 있습니다. 이 숫자는 항상 정수이며 일반적으로 길이가 약 1-14입니다.
내 파일 어딘가에 새 열을 추가하고 싶습니다.첫 번째만첫 번째 예에서는 2458, 45, 749와 같은 정수입니다. 그런 다음 이 정수를 키 값으로 사용하여 조회 테이블에서 여러 값을 조회하려고 합니다.
내 파일 중 일부에는 70,000줄이 있어서 수동으로 편집할 수 없습니다...
해결책은 기본적일수록 좋습니다. bash, sed 또는 awk를 사용하여 수행할 수 있나요?
예시 테이블은 다음과 같습니다(올바른 설명은 다음과 같습니다).
1 2 3 4 c.2458C>T
a b c d c.45_46delAA
a1 b2 c3 d4 p.Ala78_Arg80del
(참고: 열은 공백이 아닌 탭으로 구분됩니다.)
형식에는 사양이 있습니다.인간 게놈 변이 컨소시엄. 어떤 프로그램도 이 형식을 사용하지 않지만(희망합니다!) 사람들은 출판물과 의료 보고서에 이 형식을 사용합니다. 다음과 같은 최신 형식다양한 호출 형식도입되었으므로 구문 분석하기가 더 쉽습니다.
답변1
설명에 따라 탭으로 구분된 파일을 입력으로 가정합니다. 예:
$ cat file
1 2 3 4 c.2458C>T 6
a b c d c.45_46delAA or f
a1 b2 c3 d4 p.Ala78_Arg80del f6
sed 사용
다섯 번째 열의 첫 번째 정수를 찾으려면 다음을 수행하세요.
$ sed -r 's/([^\t]*\t){4}[^[:digit:]]*([[:digit:]]+).*/\2/' file
2458
45
78
위의 내용은 GNU에서 테스트되었습니다 sed
. OSX 또는 기타 BSD 시스템의 경우 다음을 시도하십시오.
sed -E 's/([^\t]*\t){4}[^[:digit:]]*([[:digit:]][[:digit:]]*).*/\2/' file
awk를 사용하세요
$ awk '{sub(/^[^[:digit:]]*/, "", $5); sub(/[^[:digit:]].*/, "", $5); print $5;}' file
2458
45
78
답변2
@ John1024의 예제 텍스트를 사용하면 이는 GNU-awk에만 해당됩니다.
gawk -F '\t' -v OFS='\t' 'match($5, /[[:digit:]]+/, m) {$(++NF) = m[0]} 1' file
생산하다
1 2 3 4 c.2458C>T 6 2458
a b c d c.45_46delAA or f 45
a1 b2 c3 d4 p.Ala78_Arg80del f6 78
아니면 펄
perl -F'\t' -lane 'print join "\t", @F, $F[4]=~/(\d+)/' file
답변3
Glenn jackman의 GNU/AWK 답변은 우아하지만 더 간단합니다.
awk 'BEGIN {FS=OFS="\t"} match($5,/[0-9]+/,arr) {print $0,arr[0]}' file
답변4
발생으로 대체 할 sed
수 있으므로 다섯 번째 항목만 필요합니다.\t
<ab>- 분리된[1]다른 가능한 일치 항목을 제외하여 필드와 그 안의 모든 숫자:
sed 's/[^\t0-9]*\([0-9]*\)[^\t]*/\1/5' <infile
다른 예제를 클립보드에 복사한 후 다음을 수행했습니다.
xsel -bo | unexpand -a | sed ...
... unexpand
-a
통행료<탭>실제 크기로 변환된 공간 순서<탭>. 그리고 그걸 프린트해서...
1 2 3 4 2458 6
a b c d 45
a1 b2 c3 d4 78 f6
...5번째 열의 첫 번째 정수만 분리합니다. 하지만 이것이 당신이 원하는 것인지 확실하지 않습니다. 한 줄의 다섯 번째 열에 있는 첫 번째 정수만 원한다면 훨씬 쉽습니다.(그리고 더 빠르게).
<infile \
cut -f5 | tr -cs '0-9\n' \\t |
expand -t1,2,4 | cut -d' ' -f-2
...첫 번째 cut
는 다섯 번째입니다.<탭>- 분리된[2]행당 완전한 데이터 필드(필드당 여러 정수를 사용하여 발생할 수 있는 문제를 방지하기 위해)그런 tr
다음<탭> Ewlines 세트를 보완하는 각 -s
압축 문자 시퀀스 및-c
\n
0-9
표준 번호 [삼].
이는 출력에서 첫 번째 정수가 첫 번째 또는 두 번째 필드에 있음을 의미합니다. 첫 번째 필드가 이제 비어 있기 때문입니다.(<탭>에 의해 시작됨)또는 기억하는 대로 접두사가 붙어 있는지 여부에 따라 일련의 숫자를 사용합니다. 그래서 나의 expand
첫 번째와 두 번째 CD<탭>-한 칸, 세 번째 칸 위치에서 줄에서 중지 - 공백으로 구분된 필드 목록을 빈 첫 번째 필드 또는 빈 세 번째 필드로 효과적으로 채웁니다. 여기에서 cut
처음 두 필드를 직접 출력할 수 있습니다.
2458
45
78
...내가 사용한 예제에 대한 결과는 다음과 같습니다. 모두 다음과 같이 만들어졌기 때문입니다.[cp].그러니 모두가 리드를 갖고 있지<탭>그러나 그렇지 않은 사람들은 비틀거리며 떠날 것입니다. 또는 각 정수를 공백으로 구분하여 모든 결과를 한 줄로 압축하려면 |xargs
명령에 추가하고 다음을 얻을 수 있습니다.
2458 45 78
노트
이스케이프 는
\t
문제의 표준 이스케이프가 아니며sed
문자 클래스의 맥락에서는 백슬래시 와 문자가 각각 자신을 나타내기[bracket-expression]
때문에 표준을 명백히 위반하는 것이라고 주장할 수도 있습니다 . 여기서는 읽을 수 있는 의도를 더 명확하게 표시하기 위해 이스케이프를 사용하고 있지만 아마도 리터럴을 사용해야 할 것입니다.\
t
<탭>그 자리에.cut
다음으로 구분됨<탭>기본값은 문자이므로 이 경우 일반-d [delim-char]
옵션은 필요하지 않습니다 . 하지만 이유를 설명하기 위해 이 메모도 추가되었습니다.링크에서 언급했듯이 POSIX 표준에서는
[:digit:]
문자 클래스에 다음이 포함되어야 합니다.0123456789모든 로케일의 문자 및 정렬 순서는 클래스의 다른 포함보다 우선합니다. C가 아닌 로케일에는 다른 지역화된 숫자 세트가 포함될 수도 있습니다. GNU는tr
여러 바이트로 표시될 수 있으므로 이를 올바르게 처리하지 못할 수 있습니다.오직그럼에도 불구하고 표준 숫자 집합은 대부분의 경우 가장 덜 놀라운 결과일 가능성이 높으므로 다음과 같은 경우[:digit:]
가 아니면 사용하세요.정말표준 아라비아 숫자 세트의 문자와 일부 문자를 일치시키려는 경우다른로케일에 따른 숫자 집합은 바람직하지 않을 수 있습니다.