각 열에 숫자가 포함된 행 수를 반환합니다.

각 열에 숫자가 포함된 행 수를 반환합니다.

이 질문에 대한 답변을 사용해 보았지만 특정 요구 사항에 맞게 조정할 수 없었습니다.

https://stackoverflow.com/questions/58005013/count-the-number-of-rows-per-column-in-bash-shell

내 목표는 csv 파일을 읽고 각 열의 개수를 반환하는 bash 스크립트를 작성하는 것입니다. 개수는 대시, 마침표, 콜론 등의 숫자 값이 포함된 행의 수입니다.

다음과 같은 csv 파일이 제공됩니다.

2012-01-01 12:01:01, 1,3.2,NA,9,P
2012-01-01 12:01:01, 1,3,5,9,P
2012-01-01 12:01:01, 1,Bad,5,9,P
2012-01-01 12:01:01, 1,3,5,9,P
2012-01-01 12:01:01, 1,3,NA,9.7,P

내 결과는 다음과 같습니다.

5,5,4,3,5,0

답변1

사용 awk:

awk -F, -v OFS=, '
   { gsub(/[:. -]/, ""); for(c=1; c<=NF; c++) if($c==$c+0) count[c]++ }
END{ for(i=1; i<c; i++) printf "%d%s", count[i], (i+1<c?OFS:ORS) }' infnile

산출:

5,5,4,3,5,0

답변2

이를 수행하는 방법에는 여러 가지가 있습니다.

perl -sF, -lane 'my $i;
  $s[$i++] += /^\h*\d/ for @F;
  }{print @s;
' -- -,=, yourfile.csv

GNU sed + rs + awk + 붙여넣기 유틸리티:

sed -E '
  s/(^|,)[0-9][^,]*/\11/g
  s/(^|,)[^0-9,]*/\10/g
' yourfile.csv |
rs -Tc,  |
awk '{print gsub(/1/,"")}'|
paste -sd, -

awk -F, -v OFS=, '
{
  for (i=1; i<=NF; i++)
    s[i] += $i ~ /^ *[0-9]/
}
END {
  for (i=1; i in s; i++)
    printf "%s%s", s[i], \
      (i+1 in s) ? OFS : ORS
}' yourfile.csv

답변3

정규식을 사용하여 쉼표로 구분된 각 필드를 테스트할 수 있습니다(예: 10진수가 포함되어 있는지 확인). 이를 요소 측정항목으로 변환하고 실행 횟수를 계산합니다.

예를 들어 Perl을 사용하는 경우:

$ perl -F, -MList::MoreUtils=pairwise -lne '
  BEGIN{@c = ()}
  @ind = map { scalar $_ =~ /\d/ } @F; @c = pairwise { $a + $b } @c, @ind
  }{
  print join ",", @c
' file
5,5,4,3,5,0

유사한 접근 방식은 awk에서도 간단해야 합니다. 즉, 요소를 명시적으로 반복하기만 하면 됩니다.

답변4

사용행복하다(이전 Perl_6)

raku -e 'my $a; for [Z] lines.map(*.subst(" ", :global).split(",")) { 
      $a.push: m:g/ [\d+ % <[-:.]>]+ /.elems }; say $a.join(",");'       

입력 예:

2012-01-01 12:01:01, 1,3.2,NA,9,P
2012-01-01 12:01:01, 1,3,5,9,P
2012-01-01 12:01:01, 1,Bad,5,9,P
2012-01-01 12:01:01, 1,3,5,9,P
2012-01-01 12:01:01, 1,3,NA,9.7,P

예제 출력:

5,5,4,3,5,0

위 내용은 Perl 계열의 프로그래밍 언어인 Raku로 작성된 답변입니다. 먼저 $a스칼라를 선언합니다. 그런 다음 lines내부 공백을 읽고 처리하고 map-ping 입력을 전달하고 공백 제거 subst(아무 것도 대체하지 않음)를 사용하면 됩니다. 그런 다음 각 요소(행)가 쉼표 위에 있으므로 split,이 열로 분할됩니다.

첫 번째 lines.map(*.subst(" ", :global).split(","))작업 후 열과 행은 Raku의 "zip" 연산자로 교체됩니다 [Z]. 이 연산자는 목록을 나타내는 요소(예: 테이블의 첫 번째 열을 구성하는 모든 요소)를 연속적으로 꺼내어 다음 위치까지 결합합니다. 목록의 요소가 모두 사용되었습니다.

\d그런 다음 각 열 요소는 , 또는 , 또는(Raku의 수정된 수량자 사용)을 포함하는 사용자 정의 문자 클래스로 구분된 숫자와 일치하는지 찾는 정규식에 대해 테스트됩니다 %. 각 열 일치 항목은 with 로 부울링되고 요소에 대해 합산된 다음 스칼라로 -ed됩니다. 마지막으로 결과를 반환합니다.-:.True.soelemspush$asay

주목해야 할 두 가지 문제:

  1. 물론 내가 보여드린 것(TMTOWTDI) 외에 내부 공백을 처리하는 또 다른 방법이 있습니다. 예를 들어 Raku의 :s"sigspace" 정규식 부사를 사용하는 것입니다.

  2. 입력 텍스트는 더 짧은 코드를 사용하거나 Raku 변수에 저장하지 않고 처리할 수 있습니다. 아래 샘플 코드(단, 행별 개수를 반환함):

raku -e 'for [Z] lines.map(*.subst(" ", :global).split(",")) { 
      say m:g/ [\d+ \% <[-:.]>]+ /.elems };'   

예제 출력:

5
5
4
3
5
0

https://docs.raku.org/언어/regexes#Modified_Quantifier:_%,_%%
https://raku.org

관련 정보