단순화된 csv 파일의 모든 데이터 필드의 최대 문자 길이를 계산하고 txt로 출력합니다.

단순화된 csv 파일의 모든 데이터 필드의 최대 문자 길이를 계산하고 txt로 출력합니다.

많은 데이터 필드(>50)가 포함된 단순화된 CSV(한 줄에 최대 한 줄)가 있는 경우 각 데이터 필드의 최대 문자 길이를 어떻게 계산한 다음 모든 개수를 txt 파일로 내보낼 수 있습니까? 그런데 열 헤더가 포함된 파일의 첫 번째 줄을 무시하고 싶습니다.

예를 들어, 입력이 주어지면

These,are,the,column_headings_which_may_be_very_long_but_they_don't_count
abcdefghij,abcdefghijk,abcdefghijkl,abc
aardvark,bat,cat,dog
ant,bee,cow,abcdefghijklm

최종 결과는 다음과 유사할 수 있습니다. 여기서 첫 번째 열은 원본 파일의 데이터 필드를 나타내고 두 번째 열은 필드의 최대 길이를 나타냅니다.

1 | 10
2 | 11
3 | 12
4 | 13

즉, 열 1의 가장 긴 값은 10( abcdefghij) 길이이고, 열 2의 가장 긴 값은 11( abcdefghijk) 길이입니다.

나는 이 사이트에서 몇 가지 조사를 했고 특정 데이터 필드를 지정할 때 매우 간단한 방법으로 최대 길이를 계산하는 여러 가지 방법을 찾았습니다. 예를 들어, 파일에서 두 번째 필드의 최대 길이를 계산하려면 cut 및 wc 명령을 사용하십시오.

cut -d, -f2 test.csv | wc -L  

하지만 어떻게 명령을 가져와 모든 데이터 필드에 반복한 다음 출력할 수 있습니까?

답변1

귀하의 질문을 올바르게 이해하면 귀하의 요구 사항이 충족됩니다.

awk -F, 'NR!=1 { if (max_NF < NF) max_NF = NF;
                 for (i=1; i<=NF; i++) if (max[i] < length($i)) max[i] = length($i) }
         END   { for (i=1; i<=max_NF; i++) printf "%-2d | %d\n", i, max[i] }'

답변2

샘플 파일에 대한 링크는 표시되지 않지만 awk명령을 사용하여 이 작업을 수행할 수 있습니다.

보유하고 있는 구분 기호와 계산해야 하는 정확한 필드를 지정할 수 있는 경우.

awk '{ FS = "," } ; { if(NR!=1) gsub(/"/, "", $2) ; print NR "|" length($2) } ' test.csv

이 출력을 원하는 파일로 리디렉션할 수 있습니다.

답변3

사용밀러( mlr)각 필드 값의 최대 길이를 계산합니다. 입력은 CSV로 읽히고 출력은 "xtab" 파일(파일당 하나의 키+값 쌍)로 생성됩니다.

$ mlr --c2x stats1 -a maxlen --fr . file
These_maxlen                                                       10
are_maxlen                                                         11
the_maxlen                                                         12
column_headings_which_may_be_very_long_but_they_don't_count_maxlen 13

--fr .이 작업의 인수는 stats1이름이 정규식과 일치하는 모든 필드 .(즉, 명명된 각 필드)의 최대 길이를 계산하는 것입니다.

보시다시피 Miller는 필드 이름을 유지하고 _maxlen각 필드에 접미사를 추가했습니다.

첫 번째 행이 헤더가 아닌 레코드인 것처럼 CSV 파일을 읽으려면 해당 첫 번째 행을 제거하고 동일한 최대 계산을 수행합니다.

$ mlr --c2x -N filter -x 'NR == 1' then stats1 -a maxlen --fr . file
1_maxlen 10
2_maxlen 11
3_maxlen 12
4_maxlen 13

추가 작업을 사용하면 모든 필드 이름에서 접미사를 제거 rename할 수 있습니다 ._maxlen

$ mlr --c2x -N filter -x 'NR == 1' then stats1 -a maxlen --fr . then rename -r '(.*)_maxlen$,\1' file
1 10
2 11
3 12
4 13

답변4

사용행복하다(이전 Perl_6)

~$ raku -ne 'BEGIN my @a;  
               unless ++$ == 1 { 
                   @a.push: $_.split(",").map: *.chars; 
               };  
             END say( ++$ ~ " | " ~ $_ ) for ([Z] @a).map: *.max;'  file

또는:

~$ raku -ne 'BEGIN my @a; 
               once next; 
               @a.push: $_.split(",").map: *.chars;  
             END say( ++$ ~ " | " ~ $_ ) for ([Z] @a).map: *.max;'  file

이것은 Perl 프로그래밍 언어 중 하나인 Raku로 작성된 답변입니다. Raku는 유니코드에 대한 고급 지원을 제공하므로 문자 수가 정확합니다.

먼저 ( awk비슷한) -ne한 줄씩 비자동 인쇄 명령줄 플래그를 사용합니다.

  1. 배열은 BEGIN블록 단위로 선언됩니다.
  2. 헤더 행(첫 번째 답변)을 제거하려면 ++$익명 카운터( )를 사용하여 첫 번째 행을 건너뛰세요. 또는 (두 번째 답변) 다음을 once next사용할 수 있습니다.
  3. split블록/루프 본문 내에서 각 줄은 쉼표로 읽혀지고 각 결과 요소는 map문자 수를 얻기 위해 입력됩니다. 이것들은 배열 chars로 푸시됩니다 .@a
  4. 모든 라인을 읽고 나면 END블록이 실행됩니다. 행과 열이 교환되도록 배열이 변환 @a됩니다 . [Z]이런 일이 발생하면 map각 배열 위치의 요소로 들어가서 익명 카운터를 max사용하여 줄 번호를 제공하여 .finally 출력 데이터를 얻을 수 있습니다(문자열 연결은 물결표를 통해 수행됨).++$~

입력 예:

These,are,the,column_headings_which_may_be_very_long_but_they_don't_count
abcdefghij,abcdefghijk,abcdefghijkl,abc
aardvark,bat,cat,dog
ant,bee,cow,abcdefghijklm

예제 출력:

1 | 10
2 | 11
3 | 12
4 | 13

참고: 행당 열 수를 확인하는 동안 오류가 발생하지 않습니다. [Z]변환은 단순히 과도한 수의 행을 공통 행(예: 예에서는 4개 열)으로 자릅니다. 행당 열 수에 관계없이 Raku에서 이 작업을 수행하려면 아래 첫 번째 링크를 참조하세요.

https://unix.stackexchange.com/a/774828/227738
https://docs.raku.org/언어/unicode
https://raku.org

관련 정보