아래와 같은 입력 파일이 있습니다. 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
답변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
.
선행 및 반복 구분 기호를 지원하는 옵션이 있지만 -n
Debian 확장으로 문서화되어 있습니다(그리고 내 Mint(Ubuntu) 배포판에서도 작동합니다). 그렇지 않은 경우 -n
null 값은 삭제되고(즉, 첫 번째 줄과 마지막 줄 구분 기호는 무시됨) 인접한 여러 구분 기호가 병합됩니다.
$ 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}" "${@:-}"