awk를 사용하여 500개의 파일을 필터링한 다음 결과를 단일 파일로 분류합니다.

awk를 사용하여 500개의 파일을 필터링한 다음 결과를 단일 파일로 분류합니다.

내가 있는 디렉터리에는 수천 개의 파일이 있지만 필터링하려는 파일에는 모두 다음 구문이 있습니다.*.imputed.*_info

awk를 사용하여 데이터의 다섯 번째 열 값이 0.50보다 큰 각 파일의 레코드를 필터링하고 싶습니다. 다음 방법을 사용하면 됩니다 awk '{if($5 >= .5) {print}}' filename.

그것도 작동합니다. 그런 다음 500개 정도의 파일 전체를 반복하면서 이 기준을 충족하는 각 파일의 레코드를 연결해 보았습니다.

다음을 시도했지만 구문이 올바르지 않습니다.

touch snplist.txt
for name in *.imputed.*_info; do
    snps="awk '{if($5 >= .5) {print}}' $name"
    cat snplist.txt "$snps" > snplist.txt
done

답변1

코드는 반복할 때마다 출력 파일을 덮어씁니다. 당신도 실제로 전화를 걸지 않았습니다 awk.

당신이하고 싶은 일은 다음과 같습니다

awk '$5 >= 0.5' ./*.imputed.*_info >snplist.txt

그러면 awk모든 파일이 한 번에 호출되고 쉘의 확장된 와일드카드 패턴 순서에 따라 하나씩 반복됩니다. 파일에 있는 줄의 5번째 열이 0.5보다 크거나 같으면 해당 줄이 출력됩니다( snplist.txt). 이는 조건과 연결된 작업(블록)이 없는 경우 {...}기본 작업이 현재 행을 출력하는 것이기 때문에 작동합니다.

당신이 가지고 있다면파일 수(천 개)로 인해 "매개변수 목록이 너무 김" 오류가 발생할 수 있습니다. 이 경우 다음을 반복해야 할 수도 있습니다.

for filename in ./*.imputed.*_info; do
    awk '$5 >= 0.5' "$filename"
done >snplist.txt

결과는 awk변수에 저장될 필요가 없습니다. 여기서는 출력됩니다.주기(따라서 루프 내의 모든 명령)은 로 리디렉션됩니다 snplist.txt.

수천 개의 파일의 경우 awk각 파일을 개별적으로 호출해야 하므로 속도가 매우 느립니다.

작업 속도를 높이려면 단일 호출에 파일이 너무 많으면 다음과 같은 방법을 awk사용하는 것이 좋습니다 .xargs

printf '%s\0' ./*.imputed.*_info | xargs -0 awk '$5 >= 0.5' >snplist.txt

그러면 파일 이름 목록이 생성되어 printfnull로 끝나는 목록으로 전달됩니다. xargs유틸리티 xargs는 이를 받아 awk시작합니다 .가능한 한 많이한 번, 일괄적으로. 전체 파이프라인의 출력은 로 리디렉션됩니다 snplist.txt.

이 대안은 사용자 가 Null로 끝나는 입력을 읽기 위한 비표준 옵션을 구현하는 명령이 xargs있는 Linux와 같은 Unix를 사용한다고 가정합니다 . 또한 쉘을 사용하고 있다고 가정합니다 .xargs-0bash내장 printf유틸리티( kshOpenBSD의 기본 셸은 내장 유틸리티가 없으므로 여기서는 작동하지 않습니다).


zsh쉘 의 경우 (즉, 아님 bash):

autoload -U zargs
zargs -- ./*.imputed.*_info -- awk '$5 >= 0.5' >snplist.txt

이는 기본적으로 로드 가능한 쉘 함수 zargs를 다시 구현한 것 입니다. 자세한 내용은 (함수 로딩 후) 및 설명서를 참조하세요.xargszshzargs --helpzshcontrib(1)

답변2

이렇게 하세요:

awk '$5 >= .5' *.imputed.*_info > snplist.txt

답변3

find나는 이런 종류의 물건을 사용하는 습관이 있습니다.

find . -type f -name "*.imputed.*_info" -exec awk '$5 >= 0.5' {} \; > ./snplist.txt

관련 정보