텍스트 파일에서 특정 열의 문자열 값을 분할하는 방법

텍스트 파일에서 특정 열의 문자열 값을 분할하는 방법

Linux 시스템에 두 개의 열이 있는 텍스트 파일이 있습니다.

  • 1열 = id_no(대부분 5자리, 일부는 6자리);
  • 열 2 = Genetic_markers(전체 길이 50674비트);
12345 0102010205
54322 2221110051
123456 1122011510

파일을 다음과 같이 변경하고 싶습니다.

 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0
  1. 첫 번째 열을 숫자에 표시된 대로 오른쪽에 정렬되도록 어떻게 변경할 수 있나요?

  2. 두 번째 열의 숫자 사이의 공백을 변경하는 가장 안정적인 방법을 알려줄 수 있는 사람이 있습니까? 코드의 요소와 그 기능을 설명해주세요.

감사해요

답변1

그리고 perl:

$ perl -lane 'printf "%6s %s\n", $F[0], join " ", split "", $F[1]' <your-file
 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0

-lane( 를 사용 -n하면 한 번에 하나의 레코드를 읽고 wk가 행을 필드로 분할 하고 레코드에서 ine 구분 기호를 제거하기 때문에 -e레코드를 사용하여 표현식을 실행합니다 .) 다음과 같이 작동합니다.$_-aa@F-llperlawk

여기서는 printf공백을 사용하여 첫 번째 필드의 길이를 6으로 왼쪽 채운 다음 join공백을 사용하여 두 번째 필드를 문자 구성 요소로 분할합니다.

답변2

오른쪽 정렬을 하려면 파일에서 가장 긴 숫자의 길이를 찾거나, 그냥 큰 숫자를 골라서 사용하면 됩니다. 예를 들어, 10개의 공백을 채울 수 있습니다.

$ printf '%d\n' 123
123
$ printf '%10d\n' 123
       123

이 접근 방식이 충분하다면 다음을 수행할 수 있습니다.

$ awk '{ gsub(/./," &",$2); printf "%10d%s\n",$1,$2}' file 
     12345 0 1 0 2 0 1 0 2 0 5
     54322 2 2 2 1 1 1 0 0 5 1
    123456 1 1 2 2 0 1 1 5 1 0

여기서는 두 가지 일만 일어나고 있습니다.

  • gsub(/./," &",$2);: 이것 gsub(G글로벌아들.stitution) 함수는 사용자가 제공한 정규 표현식의 모든 항목을 사용자가 제공한 대체 항목으로 대체합니다(여기에서는 "모든 문자"라는 의미만 부여합니다). &"정규 표현식과 일치하는 모든 것"을 의미하는 특별한 의미를 가지므로 &대체 효과는 각 문자 앞에 공백을 삽입하는 것입니다. 마지막 매개변수는 입력이며 여기서는 두 번째 필드를 제공합니다 $2.
  • printf "%10d %s\n",$1,$2printf: 형식화된 문자열을 인쇄하는 데 사용합니다 . %10d이는 "내가 준 숫자를 인쇄하고 10개의 공백으로 채웁니다"를 의미하며 %s이는 "이 문자열을 인쇄합니다"를 의미합니다. 그래서 우리는 10개의 공백으로 채워진 첫 번째 필드를 인쇄한 다음 수정된 두 번째 필드를 인쇄하도록 지시합니다 gsub.

최소값만 채우려면 파일을 두 번 읽어야 합니다. 먼저 가장 긴 첫 번째 필드의 길이를 가져옵니다.

$ awk -v max=0 '{ if(length($1) > max){ max=length($1) }} END{print max}' file 
6

이를 통해 더 구체적으로 설명할 수 있습니다.

$ awk '{ k=gsub(/./," &",$2); printf "%6d%s\n",$1,$2}' file 
 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0

답변3

awkany 및 GNU 사용 column(용 -R):

$ awk '{gsub(/./," &",$2)} 1' file | column -tR1
 12345  0  1  0  2  0  1  0  2  0  5
 54322  2  2  2  1  1  1  0  0  5  1
123456  1  1  2  2  0  1  1  5  1  0

-o' '필드 사이의 공백이 정말로 중요하다면 다음을 추가하세요.

$ awk '{gsub(/./," &",$2)} 1' file | column -o' ' -t -R1
 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0

답변4

사용행복하다(이전 Perl_6)

~$ raku -ne '.split(" ") andthen put sprintf("%6d", .[0]), .[1].comb;'  file 

#OR

~$ raku -ne '.words andthen put sprintf("%6d", .[0]), .[1].comb;'  file

Raku는 Perl 계열의 프로그래밍 언어입니다. 위는 Raku의 -ne비자동 인쇄 라인별 플래그를 사용합니다. 기본적으로 이 -n플래그는 줄 끝에서 구분 기호를 제거합니다. 그런 다음 print후행 개행 문자(기본값)를 생략하거나 , 이렇게 put하면 후행 개행 문자가 추가됩니다(put종결자를 사용하여 인쇄).

첫 번째 답변에서 그 줄은 분명히 .split단일 공백(의 약어 $_.split)에 있습니다. 두 번째 답변에서는 Raku의 .words루틴을 공백으로 분할하는 데 사용합니다. 그런 다음 각 열의 출력 형식을 지정할 수 있도록 연결이 andthen다시 로드됩니다 . $_첫 번째 열(예: .[0])은 형식이 지정 sprintf되고 두 번째 열(예: .[1])은 comb단일 문자로 편집되어 반환됩니다.


참고: "ID"가 실제로 (10진수) 부호 없는 정수인 경우 내부적 으로 에 표시된 대로 대신 sprintf사용할 수 있습니다 .udsprintf("%6u", …)


입력 예:

12345 0102010205
54322 2221110051
123456 1122011510

예제 출력:

 123450 1 0 2 0 1 0 2 0 5
 543222 2 2 1 1 1 0 0 5 1
1234561 1 2 2 0 1 1 5 1 0

참고: 파일에 빈 줄이 포함되어 있을 때 오류 발생을 방지하려면 if빈 줄을 제거하는 조건을 추가할 수 있습니다.

~$ raku -ne 'if .chars { .words andthen put sprintf("%6d", .[0]), .[1].comb};'  file

#OR

~$ raku -ne 'if $_ .= words {put sprintf("%6d", .[0]), .[1].comb};'  file

빈 줄을 유지하려면 Raku's를 사용할 수 있습니다.3위안운영자:

~$ raku -ne '.chars ??  ( .split(" ") andthen put sprintf( "%6d", .[0]), .[1].comb) !! "".put;'  file

#OR

~$ raku -ne '$_ .= split(" ", :skip-empty) ?? (put sprintf( "%6d", .[0]), .[1].comb) !! "".put;'  file 

https://docs.raku.org/routine/sprintf
https://docs.raku.org/routine/%3F%3F%20%21%21
https://raku.org

관련 정보