Bash는 여러 파일의 열을 연결합니다.

Bash는 여러 파일의 열을 연결합니다.

제 주변에도 하나 있어요20pathtofiles.in파일이 다른 폴더에 있는 경우 whichlists 라는 별도의 파일을 만들었습니다.정보:

/home/users/gray_wolf/unix/File_1.tsv
/home/users/gray_wolf/unix/File_2.tsv
.
.
.

각 파일에는 대략적인 내용이 포함되어 있습니다.11 목록에 대한100,000 좋아요. 예:

파일 1:

Chromosome    begin    end    .....
chr1          1000     2000
chr1          2000     3000
chr1          4000     5000
chr1          5000     6000
chr1          10000    12000
chr1          12000    13000

파일_2:

Chromosome    begin    end    .....
chr1          1000     2000
chr1          4000     5000
chr1          5000     6000
chr1          6000     7000
chr1          10000    12000
chr1          13000    14000

최종 필수 파일 형식:

Chromosome    begin    end     Column5                    column8 
chr1          1000     2000    File1,File2,File3...       File1,File2,File3...
chr1          2000     3000    File1,File2(0),File3       File1,File2(0),File3...
chr1          4000     5000    File1,File2,File3...       File1,File2,File3...
chr1          5000     6000    File1,File2,File3...       File1,File2,File3...
chr1          6000     7000    File1,File2,File3...       File1,File2,File3...
chr1          10000    12000   File1,File2,File3...       File1,File2,File3...
chr1          12000    13000   File1,File2,File3...       File1,File2,File3...
chr1          13000    14000   File1(0),File2,File3...    File1(0),File2,File3...

pathtofile.in내가 이것을 다음과 같이 전달할 때 :script.sh

./script.sh < pathtofile.in

...스크립트는 주어진 파일을 읽고 pathtofiles.in출력 해야 합니다.5- 열 탭으로 구분된 목록입니다. 첫 번째출력 열은 다음과 같아야 합니다. 목록각 파일의결합된. 이것4출력 열은 해당 행이어야 합니다.5쉼표로 구분된 모든 입력 파일의 열( 과 동일한 순서 pathtofiles.in)입니다. 이것5출력 열은 해당 행이어야 합니다.8쉼표로 구분된 모든 입력 파일의 열입니다.

특정 입력 행에 열이 누락된 경우8, (또는 열5), 해당 위치에 "(0)"을 출력합니다.

나는 열을 개별적으로 자르고반죽/가입하다기능을 수행하지만 각 파일마다 줄 수가 다르기 때문에 순서가 잘못됩니다. 어떻게 사용하나요?또는 아래에서 실행되는 다른 명령세게 때리다?

미리 감사드립니다.

~엠

답변1

간단한 해결책: paste세 개의 파일을 함께 넣고 필요한 열을 가져옵니다.

paste -d' ' file1 file2 file3  |\
awk 'BEGIN { FS = " +" } { NR ==1} { printf "%-10s%-7s%-7s  %-12s  %-12s\n" $1,$2,$3,$6,$7 } { NR >=2 } { printf "%-10s%-7s%-7s  %s,%s%s  %s%s%s\n" $1,$2,$3,$6,$7,$8,$9,$10,$11 } '

이는 파일 및 출력 형식 기본 설정에 따라 채택되어야 합니다. 설명하다:

1) paste -d' '-> 공백을 구분 기호로 사용하여 트리 파일을 수직으로 병합합니다 -d.

2) 파이프로 연결 하고 가독성을 위해 awk새 줄에 명령을 계속합니다 .|\

2.1) BEGIN { FS = " +" }- 다음 모두에 대해 하나 이상의 (+) 공백을 필드 구분 기호로 사용하십시오.

2.2) 첫 번째 줄에 { NR ==1}1,2,3,6,7( $1,$2 ...) 필드를 다음 형식으로 인쇄합니다(큰따옴표로 묶음).

%-10s10자 길이의 문자열이 수정되었습니다(나머지는 공백으로 채워지고 왼쪽 정렬됨).

같은 길이의 7자 두 배, 공백 2개, 12자 긴 문자열, 공백 2개, 12자 문자열입니다. \n끝에 새 줄을 추가하십시오.

(섹션에서 확인 { printf "%-10s%-7s%-7s %-12s %-12s\n" $1,$2,$3,$6,$7 })

2.2) 데이터: 두 번째 행부터 { NR >=2 }시작하여 열을 인쇄합니다 . $1,$2,$3,$6,$7,$8,$9,$10,$11형식은 다음과 같습니다.%-10s%-7s%-7s %s,%s,%s %s,%s,%s\n

위와 유사하지만 이제 예를 들어 열 6,7,8은 임의 길이이며 쉼표로 구분됩니다.%s,%s,%s

답변2

모든 입력 파일을 동시에 열 수 있는 프로그램이 필요합니다. 구문이 awk있으므로 that 또는 perl이 좋은 선택이 될 것입니다. getline <file또는 당신이 알고 있는 다른 고급 언어.

이를 위해 저는 Perl을 선택하겠습니다. 가지다http://www.bioperl.org/유전자 서열 데이터 파일 형식을 처리하기 위해 특별히 설계된 Perl 모듈을 사용합니다.

생각보다 복잡할 수도 있다는 걸 깨닫고 중간에 포기했습니다. 입력 파일 중 하나가 다른 파일과 다른 열 2/3 값을 갖는 일반적인 경우를 처리하려면 다방향 diff 유형 알고리즘을 수행해야 합니다. 찾고 있는 시작/끝 쌍과 일치하는 항목을 찾을 때까지 그 줄을 계속 읽을 수는 없습니다. 왜냐하면 그것이 존재하지 않을 수도 있기 때문입니다.

따라서 가장 좋은 방법은 우선순위 대기열이나 정렬된 입력을 받는 것입니다. 각 파일에 대해 대기열에 삽입한 줄이 현재 파일 처리를 시작하기 전에 줄 뒤에 있을 때까지 읽습니다. (또는 방금 읽은 줄이 pqueue의 새로운 꼬리가 될 때까지).


파일이 한 번에 메모리에 쉽게 들어갈 수 있다면 연관 배열(column2:column3으로 인덱싱됨)을 사용하여 출력을 작성하면 코딩이 더 쉬워집니다. 그러면 우선 순위 대기열이 필요하지 않으며 다음에 어떤 파일을 진행할지 알아낼 필요도 없습니다.


이것은 지금까지 내 코드입니다. 순서가 잘못된 상황을 처리하거나 병합하지 않고 입력 라인을 반복합니다. 나는 이것이 합리적인 스택 교환 답변 범위보다 크다는 것을 깨달았을 때 중단했지만 이것이 시작을 제공할 수 있습니다.

#!/usr/bin/perl -w

my @f = @ARGV;  # list of files to process


sub getfields($) {
    my $file = $_[0];
    my $ln = <$file> or return ();  # sentinel for EOF
    my @fl = split ' ', $ln, 9;
    return ( $fl[0], $fl[1], $fl[2], $fl[4], $fl[7] );
}

# open each filename in @f, storing the file handles in @f.
foreach (@f) {
    open $_, '<', $_  or die "opening $_: $!";
}

my $newdata = 0;
do {
    $newdata = 0;
    foreach my $fd (@f) {
    my @fl = getfields($fd);
    next if ! (@fl);  # end of file on $fd.  TODO: take it out of @f?
    $newdata = 1;
    print join("|", @fl), "\n";  # debug
    }
} while ($newdata);  # done when all files are EOF

관련 정보