텍스트 처리 라인은 행에서 열까지 Awk를 차단합니다.

텍스트 처리 라인은 행에서 열까지 Awk를 차단합니다.

아래와 같은 입력 파일이 있습니다. o/p가 언급한 대로 텍스트 형식을 다시 지정해야 합니다. 나는 이 포럼에서 얻은 awk를 사용하고 있지만 목록 A 열 번호를 기반으로 합니다. 도와주세요

awk 'BEGIN{ max=0 }
 /^List/{ if(k && k>max) { max=k; idx=c } ++c; k=0 }
 NF{ a[c][++k]=$0 }
 END{ 
     for(i=1;i<=max;i++) 
         for(j=1;j<=c;j++) printf "%s%s",a[j][i],(j==c)?ORS:"\t" 
 }' filename | column -ts$'\t'  

입력하다:-

List A
Hello
how are you
fine

List B
good: Fine_health
hello: world_free
some: unkon_text
some: unkon_text1
some: unkon_text2

예상 출력

List A       List B
Hello        good: Fine_health
how are you  hello: world_free
fine         some: unkon_text
             some: unkon_text1
             some: unkon_text2

답변1

사용행복하다(이전 Perl_6)

~$ raku -e 'my @a = slurp.split("\n\n"); @a.=map(*.split("\n", :skip-empty));  \
            my $length = @a>>.elems.max;  for ^$length -> $i {  \
               print ($_[$i] // q[ ]) ~ q[|] for @a; "".say;    \
               };'  filename.txt  |  column -ts'|'

위의 답변은 Raku로 코딩되었습니다. 행은 slurp(한 번 읽음)과 split단락( \n\n)으로 구성됩니다. 단락은 배열에 할당됩니다 @a. 다음 명령문에서는 각 단락 요소가 \n행으로 구분됩니다. max배열의 요소 길이를 계산합니다 .elems@a

@a그런 다음 배열의 각 위치(읽기: 단락) print가 전체 max 로 내보내지고 $length각 위치(읽기: 행)의 하위 요소가 정의되지 않고( //"define or" 연산자 사용) q[ ]공백이 삽입되었습니다("자리 표시자" "문자" 열). 열은 ~후행 |열과 연결되고 각 행은 종료됩니다(개행 문자 사용 "".say;).

OP에 원하는 출력을 제공하기 위해 Unix 유틸리티를 column사용하여 삽입된 |막대 구분 기호의 열을 분할합니다. Raku 전용 솔루션의 경우 대체하면 탭으로 구분된 출력이 ~ q[|]반환됩니다 .~ qb[\t]

입력 예:

List A
Hello
how are you
fine

List B
good: Fine_health
hello: world_free
some: unkon_text
some: unkon_text1
some: unkon_text2

예제 출력:

List A        List B
Hello         good: Fine_health
how are you   hello: world_free
fine          some: unkon_text
              some: unkon_text1
              some: unkon_text2

https://raku.org
https://rakudo.org

답변2

입력 및 출력 예제에서는 두 목록을 연결하려고 함을 의미합니다. 이 작업을 수행하는 데 awk가 필요하지 않습니다. 입력 파일을 lista와 listb의 두 개로 분할하고 붙여넣기 명령을 사용하여 연결합니다.

paste lista listb

입력 파일을 자동으로 두 개의 파일로 분할한 다음(각 부분이 하나 또는 두 개의 빈 줄로 구분된다고 가정) 공백에 대한 RS 옵션과 함께 awk를 사용할 수 있습니다.

awk -v RS= '{print > ("list" NR ".txt")}' listall

그러면 list1.txt 및 list2.txt 파일이 생성됩니다.

그 다음에:

paste list1.txt list2.txt

답변3

게시된 스크립트는아니요일하다. 처음 4줄만 인쇄합니다. 목록 B의 마지막 두 줄은 생략됩니다.

문제는 k각 목록의 행 수를 계산하는 것입니다. 하지만 그것은 max다음에 만 저장됩니다.시작각 목록의 길이이므로 두 번째 목록의 길이는 고려되지 않습니다.

해결 방법은 if(k && k>max) { max=k; }마지막 목록을 읽은 후 END 블록의 첫 번째 줄로 반복하는 것입니다.

이것은 또 다른 오류를 드러냅니다. 마지막 두 행은 열에 나열되지 않고 열 1에 나타납니다. 문제는 column길이가 0인 첫 번째 열이 인식되지 않는 것 같습니다 . .각 값의 시작 부분에 a를 강제로 적용하면 열에 B가 올바르게 나열됩니다.

개인적으로 저는 awk로 열화하고 싶습니다. 각 열에 있는 항목의 최대 길이를 저장하고 %-*s너비 지정자로 구분합니다. 아마도 이것이 사용되지 않은 변수 idx의 용도일 것입니다.

편집: 예, 분명히 열의 실수입니다. 이 탭은 작업용 Four이지만 무시용은 아닙니다 Three.

선행 및 반복 구분 기호를 지원하는 옵션이 있지만 -nDebian 확장으로 문서화되어 있습니다(그리고 내 Mint(Ubuntu) 배포판에서도 작동합니다). 그렇지 않은 경우 -nnull 값은 삭제되고(즉, 첫 번째 줄과 마지막 줄 구분 기호는 무시됨) 인접한 여러 구분 기호가 병합됩니다.

$ cat -vet foo
One$
 Two$
^IThree$
q^IFour$
$ column -t -s $'\t' foo | cat -vet
One$
 Two$
Three$
q      Four$

편집 2: 이 버전에는 더 많은 기능이 있습니다.

(a) 내부적으로 표 작성을 수행하여 명령 오류를 방지합니다 column(또한 전체 데이터 세트를 메모리에 저장하기 위한 awk 및 열의 추가 프로세스 및 메모리 오버헤드를 방지합니다).

(b) 여러 파일 인수를 허용합니다(기본적으로 표준 입력이므로 파이프라인에서 작동함).

(c) 두 개가 아닌 원하는 수의 출력 열에서 작동합니다.

(d) 원래 릴리스의 버그를 수정했습니다(가장 오른쪽 열의 길이는 무시되었습니다).

#! /bin/bash

Awk='
BEGIN { Gap = 2; }
/^List/ { ++col; row=0; }
NF { X[++row, col] = $0;
    if (mxrow < row) mxrow = row;
    if (len[col] < length($0)) len[col] = length($0);
}
function Column (Local, r, c) {
    for (r = 1; r <= mxrow; ++r) {
        for (c = 1; c < col; ++c) 
            printf ("%-*s", Gap + len[c], X[r,c]);
        printf ("%-s\n", X[r,c]);
    }
}
END { Column( ); }
'
    awk "${Awk}" "${@:-}" 
    

관련 정보