awk를 사용하여 새 줄을 공백으로 바꿉니다.

awk를 사용하여 새 줄을 공백으로 바꿉니다.

디렉터리의 모든 파일에서 생성된 텍스트 파일이 있습니다. 이 파일을 내가 가지고 있는 스크립트에 대한 입력으로 사용하고 싶지만 올바르게 구문 분석하려면 특정 방식으로 형식이 지정된 텍스트 파일이 필요합니다.

현재 텍스트 파일(파일 이름 목록)의 형식은 다음과 같습니다.

A1_R1.fastq.gz
A1_R2.fastq.gz
A2_R1.fastq.gz
A2_R2.fastq.gz
A3_R1.fastq.gz
A3_R2.fastq.gz

RN각 샘플이 탭으로 구분되어 동일한 줄에 있도록 쌍으로 된 읽기(이름은 같지만 값이 다른 파일)가 필요합니다 .

A1_R1.fastq.gz A1_R2.fastq.gz
A2_R1.fastq.gz A2_R2.fastq.gz
A3_R1.fastq.gz A3_R2.fastq.gz

1000개 이상의 항목이 있으므로 awk 또는 이와 유사한 것을 사용하여 파일을 수정하는 방법을 원하지만 awk에 대한 경험이 많지 않습니다.

답변1

질문에 표시된 대로 줄이 정렬되어 있다고 가정하면 이 paste명령은 다음을 수행할 수 있습니다.

$ paste - - < input_file
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz
A3_R1.fastq.gz  A3_R2.fastq.gz

-d기본 TAB 이외의 항목으로 열을 구분하려면 이 옵션을 사용하세요 paste. 간단한 공간의 경우:

$ paste -d ' ' - -  <input_file

답변2

모든 라인 쌍이 서로 인접한 표시된 입력의 경우 awk에 필요한 것은 다음과 같습니다.

$ awk '{ORS=(NR%2 ? "\t" : RS)} 1' file
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz
A3_R1.fastq.gz  A3_R2.fastq.gz

또는 아직 페어링되지 않은 경우:

$ shuf file > file1
$ cat file1
A3_R2.fastq.gz
A2_R2.fastq.gz
A1_R1.fastq.gz
A3_R1.fastq.gz
A1_R2.fastq.gz
A2_R1.fastq.gz

따라서 다음에 대한 호출을 추가해도 괜찮다면 다음을 수행하십시오 sort.

$ awk '{ORS=(NR%2 ? "\t" : RS)} 1' <(sort file1)
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz
A3_R1.fastq.gz  A3_R2.fastq.gz

아니면 awk로 페어링하세요:

$ awk -F'_' -v OFS='\t' '$1 in a{print a[$1], $0; next} {a[$1]=$0}' file1
A3_R2.fastq.gz  A3_R1.fastq.gz
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R2.fastq.gz  A2_R1.fastq.gz

마지막 스크립트에서는 경우에 따라 R2 필드가 R1 파트너보다 먼저 출력됩니다. 이것이 문제인 경우 인쇄하면서 주문할 수 있습니다.

$ awk -F'_' -v OFS='\t' '
    $1 in a { print (a[$1] < $0 ? a[$1] OFS $0 : $0 OFS a[$1]); next }
    { a[$1] = $0 }
' file1
A3_R1.fastq.gz  A3_R2.fastq.gz
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz

입력 파일에 실제로 수백만 줄이 있는 경우 delete a[$1];이전에 추가하면 next대부분의 경우 실행 시간이 빨라지고, 수천 줄에 불과하다면 그럴 가치가 없을 것입니다( delete a[$1]각 쌍을 호출하는 오버헤드와 큰 해시를 갖는 오버헤드를 비교해보세요). 표면 a[]).

출력 라인을 정렬해야 한다면 GNU awk를 사용해야 합니다 PROCINFO["sorted_in"]:

$ awk '{a[$0]} END{PROCINFO["sorted_in"]="@ind_str_asc"; for (i in a) printf "%s%s", i, (++n % 2 ? "\t" : RS) }' file1
A1_R1.fastq.gz  A1_R2.fastq.gz
A2_R1.fastq.gz  A2_R2.fastq.gz
A3_R1.fastq.gz  A3_R2.fastq.gz

그러나 사용된 솔루션과 마찬가지로 sort입력의 숫자가 여러 숫자일 수 있는 경우 예상된 순서를 생성하지 않습니다. 예를 들어 A11이전에는 알파벳순으로 정렬되었기 때문입니다 A2. 각 문자열을 별도의 알파벳 및 숫자 부분으로 분리해야 합니다. 각 부분을 별도로 정렬하거나 각 위치에 항상 동일한 숫자 알파벳 및 숫자 문자가 있도록 정규화합니다(예: A1_R1정렬하기 전에 매핑).000A0001_000R0001

답변3

사용행복하다(이전 Perl_6)


항상 쌍으로 읽고 순서가 올바른 경우:

~$ raku -e '.put for lines.rotor(2);'  file 

항상 쌍으로 읽었지만 파일 이름이 순서가 잘못된 경우:

~$ raku -e '.put for lines.sort.rotor(2);'  file 

Raku는 Perl 계열의 프로그래밍 언어입니다. @EdMorton의 탁월한 답변과 유사하게 awk파일 이름을 정렬해야 하는 경우 결과 순서는 알파벳순입니다.

https://docs.raku.org/routine/lines
https://docs.raku.org/routine/rotor
https://raku.org


파일 이름 순서에 상관없이 파일이 누락되는 경우가 있습니다.

~$ raku -ne 'BEGIN my %hash;     \  
             %hash.append: .match(/^ (<-[_]>+) _ /).[0]  =>  $_;   \
             END for %hash.sort { .values.put };'   file

#OR

~$ raku -ne 'BEGIN my %hash;     \ 
             %hash.append: m/^ (<-[_]>+) _ /.[0]  =>  $_;    \
             END for %hash.sort { .values.put };'   file 

두 번째 방법은 입력 데이터가 원본이 아닌 경우(파일 이름 누락 등)에 적합합니다. Perl 자체와 마찬가지로 Raku에는 ("non-auto-print-line") 플래그를 통해 호출되는 awk명령줄과 유사한 모드가 있습니다. -ne위에서는 BEGINa를 선언하여 이 작업을 수행합니다 %hash. 이 "한 줄짜리" 본문에서 각 줄은 .matched on입니다(여기에는 줄의 텍스트를 보유하는 테마 변수인 on 함수를 호출하는 약어가 .match있습니다 ).$_.match$_

.match(또는) 루틴 m/ … //operator는 ^줄의 시작, <-[_]>+밑줄 이외의 하나 이상의 문자 (예: 사용자 지정 부정 문자 클래스), 밑줄 자체를 _찾습니다 . _(참고용으로만 맞춤설정하세요.긍정적인캐릭터 클래스는 다음과 같습니다 <+[ … ]>:). 괄호는 밑줄이 그어지지 않은 선행 텍스트를 $0다음과 같이 캡처합니다 .[0].

.[0]따라서 각 행은 with key( $_전체 행) 으로 해석됩니다 value. => 키/값 쌍을 만드는 데 사용됩니다 . 해시 데이터 구조는 고유하게 유지되므로 동일한 값이 나타날 때 keys마다 새로운 값이 얻어집니다 . 읽기 줄 끝 에서 키를 누른 다음 각 키를 꺼냅니다.keyappendENDsortput.values

https://course.raku.org/essentials/associatives/hashes/
https://docs.raku.org/언어/hashmap
https://raku.org


입력 예:

A1_R1.fastq.gz
A1_R2.fastq.gz
A2_R1.fastq.gz
A2_R2.fastq.gz
A3_R1.fastq.gz
A3_R2.fastq.gz

출력 예(두 방법 중 하나):

A1_R1.fastq.gz A1_R2.fastq.gz
A2_R1.fastq.gz A2_R2.fastq.gz
A3_R1.fastq.gz A3_R2.fastq.gz

답변4

나는 그것의 팬입니다 sed. 인접한 전선 쌍을 쉽게 연결할 수 있습니다.

sed 'N; s/\n/'$'\t''/' < input > output

중간에 있는 것은 $'\t'단일 탭 문자를 전달하는 bash-ism이며 sed. 실제로는 리터럴 탭을 사용하겠지만 이 매체에는 이것이 명확하게 반영되지 않습니다.sed 'N; s/\n/ /' < input > output

설명하다:

  • sed첫 번째 줄부터 읽으세요.
  • 다음 입력 줄을 읽고 이를 현재 입력 줄에 추가하고 개행 문자 N로 구분하도록 지시합니다.sed
  • s명령은 줄 바꿈을 탭으로 바꿉니다.
  • 더 이상 명령이 없으면 이전 단계의 결과를 쓴 후 sed다음 줄을 읽고 루프백합니다.
  • sed입력이 소진되면 종료됩니다.

관련 정보