awk 문은 char 변수의 수를 인쇄하고 작동하지 않습니다.

awk 문은 char 변수의 수를 인쇄하고 작동하지 않습니다.

csv 파일의 가장 긴 줄을 기반으로 점선을 인쇄하는 다음은 다음과 같습니다.

awk -F ',' '
    BEGIN {
       longest_line=0
        for (i = 1; i <= NF; i++) {
           longest[i] = ""
        }
    }
    {
       for (i = 1; i <= NF; i++) {
           if (length($i) > length(longest[i])) {
               longest[i] = $i
           }
       }
    }
    
    END {
        for (i=1; i<=NF;i++) {
            longest_line += length(longest[i])
        }
        printf("%*s", longest_line, "=")
    }
'

전체 스크립트는 다음과 같습니다.

awk -F ',' -v smso="$smso" -v rmso="$rmso" 'BEGIN {
    count=1
    firstcol=0
    arraylen=1
    longest_line=0
   for (i = 1; i <= NF; i++) {
       longest[i] = ""
    }
}

{
    for (i=1;i<=NF;i++) {
            if (i==NF) {
                data[arraylen++]=$i
                data[arraylen++]="\n"
            } else {
                data[arraylen++]=$i
            }
    }
}


{
   for (i = 1; i <= NF; i++) {
       if (length($i) > length(longest[i])) {
           longest[i] = $i
       }
   }
}

END {
    for (i=1; i<=NF;i++) {
        longest_line += length(longest[i])
    }
    printf("%*s", longest_line, "b")
    for (i = 1; i <= length(data); i++) {
        if (data[i]=="\n") {
            firstcol++
           count=1  
            printf("%s", data[i])
        } else if (count==1 && i != 1) {
            printf("%s%s%s", "|", data[i], "|")
            count++
        } else {
            smso=$(tput smso)
            rmso=$(tput rmso)
            num_spaces=(length(longest[count])-length(data[i]))+1
            printf("%s%*s%s%s", (i==1?"|":""), (i==1?num_spaces-1:num_spaces), " ", firstcol==0?toupper(data[i]):data[i], "|")
            count++
        }
    }   
}'

입력 파일은 다음과 같습니다.

NUMBER,FNAME,LNAME,PHONE-TYPE:GROUPS
222-222-2222,Elizabeth,Taylor,office:beauty:
111-111-1111,Matt,Alex,personal:superhuman:cool:amazing:extra

원하는 출력은 다음과 같습니다.

==============================================================
|      NUMBER|     FNAME|  LNAME|           PHONE-TYPE:GROUPS|
|222-222-2222| Elizabeth| Taylor|              office:beauty:|
|111-111-1111|      Matt|   Alex| personal:cool:amazing:extra|

하지만 내 결과는 다음과 같습니다

                                                             =
|      NUMBER|     FNAME|  LNAME|           PHONE-TYPE:GROUPS|
|222-222-2222| Elizabeth| Taylor|              office:beauty:|
|111-111-1111|      Matt|   Alex| personal:cool:amazing:extra|

답변1

sprintf("%*s", n, string)문자열을 길이에 맞춰 왼쪽으로 채웁니다(구현에 따라 바이트 또는 문자 수 awk).n 공백이 있습니다.

문자열을 n번 반복하려면 도우미 함수를 작성하면 됩니다.

function repeat(n, string,  result) {
  while (n-- > 0) result = result string
  return result
}

여기서는 mlr즉시 이 작업(또는 유사한 작업)을 수행하고 CSV를 올바르게 처리하기 위해 다음을 사용하는 것이 좋습니다.

$ mlr --c2p --barred 고양이 파일.csv
+------------+---+---------+--------- ------- ---------------+
|숫자       |이름     |이름  |통화 유형: 그룹                      |
+------------+---+---------+--------- ------- ---------------+
| 222-222-2222 | 엘리자베스 테일러 |
111-111-1111 | 매트 | 개인: 슈퍼맨: 어메이징: 엑스트라 |
+------------+---+---------+--------- ------- ---------------+

또는 오른쪽 정렬 필드의 경우:

$ mlr --c2p --barred --right 고양이 파일.csv
+------------+---+---------+--------- ------- ---------------+
|       숫자|     이름|  이름|                      통화 유형: 그룹|
+------------+---+---------+--------- ------- ---------------+
| 222-222-2222 | 엘리자베스 테일러 |
111-111-1111 | 매트 | 개인: 슈퍼맨: 어메이징: 엑스트라 |
+------------+---+---------+--------- ------- ---------------+

mlr사용할 수 없는 경우에는 대체된 내용을 대신 awk사용하겠습니다 .perlawk

perl -MList::Util=zip -MTerm::ANSIColor -F, -lane '
  push @rows, [@F];
  $i = 0; for (@F) {
    $max[$i] = length if length > $max[$i];
    $i++;
  }
  
  END {
    $line = join("+", "", (map {"-" x ($_ + 2)} @max), "");
    print $line;
    print join("|", "", (map {colored(sprintf(" %*s ", @$_), "bold blue")} zip(\@max, shift @rows)), "");
    print $line;
    for (@rows) {
      print join("|", "", (map {sprintf " %*s ", @$_} zip(\@max, $_)), "");
    }
    print $line;
  }' file.csv

이것은 만든다:

+--------------+-----------+--------+----------------------------------------+
|       NUMBER |     FNAME |  LNAME |                      PHONE-TYPE:GROUPS |
+--------------+-----------+--------+----------------------------------------+
| 222-222-2222 | Elizabeth | Taylor |                         office:beauty: |
| 111-111-1111 |      Matt |   Alex | personal:superhuman:cool:amazing:extra |
+--------------+-----------+--------+----------------------------------------+

제목은 굵은 파란색입니다.

에서는 반복 연산자를 사용하여 perl문자열 반복을 수행합니다. 결과는 입니다 . 자세히보다.x"string" x 3stringstringstringperldoc perlop

perlPerl 모듈은 35년 동안 사용되었기 때문에 바퀴를 다시 만들 필요가 거의 없지만 Perl 모듈은 거의 모든 용도로 사용될 수 있습니다 . 우리는 이미 사용했습니다List::Util유용한 목록 조작 기능을 갖춘 모듈과Term::ANSIColor위의 컬러 텍스트를 출력하지만Text::CSVCSV 및Text::ASCIITable테이블 형식을 지정합니다.

$ perl -MText::CSV=csv -MText::ASCIITable -e '
  $c = csv(in => shift);
  $t = Text::ASCIITable->new;
  $t->setCols(shift @$c);
  $t->addRow($_) for @$c;
  print $t' file.csv
.----------------------------------------------------------------------------.
| NUMBER       | FNAME     | LNAME  | PHONE-TYPE:GROUPS                      |
+--------------+-----------+--------+----------------------------------------+
| 222-222-2222 | Elizabeth | Taylor | office:beauty:                         |
| 111-111-1111 | Matt      | Alex   | personal:superhuman:cool:amazing:extra |
'--------------+-----------+--------+----------------------------------------'

답변2

printf("%*s", longest_line, "=")

=공백 으로 longest_line-1들여쓰기된 문자를 인쇄합니다 . 당신은 이것을 원합니다 :

line = sprintf("%*s", longest_line, "")
gsub(/ /,"=",line)
print line

FWIW, 이것은 awk를 사용하여 원하는 작업을 수행하는 코드를 작성하는 방법입니다.

$ cat tst.awk
BEGIN { FS=","; OFS="|"; hdrChar="=" }
{
    for (colNr=1; colNr<=NF; colNr++) {
        val = $colNr
        vals[NR,colNr] = val
        wid = length(val)
        wids[colNr] = (wid > wids[colNr] ? wid : wids[colNr])
    }
}
END {
    for ( colNr=1; colNr<=NF; colNr++ ) {
        row = row hdrChar sprintf("%*s",wids[colNr],"")
    }
    gsub(/ /,hdrChar,row)
    print row hdrChar

    for ( rowNr=1; rowNr<=NR; rowNr++ ) {
        row = ""
        for ( colNr=1; colNr<=NF; colNr++ ) {
            row = row OFS sprintf("%*s",wids[colNr],vals[rowNr,colNr])
        }
        print row OFS
    }
}

$ awk -f tst.awk file
======================================================================
|      NUMBER|    FNAME| LNAME|                     PHONE-TYPE:GROUPS|
|222-222-2222|Elizabeth|Taylor|                        office:beauty:|
|111-111-1111|     Matt|  Alex|personal:superhuman:cool:amazing:extra|

val = $colNr또는 이와 유사하게 변경하여 val = " " $colNr " "적절하다고 생각되는 공백으로 일부 필드를 채웁니다 .

관련 정보