이 질문에 대한 답변을 사용해 보았지만 특정 요구 사항에 맞게 조정할 수 없었습니다.
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
.so
elems
push
$a
say
주목해야 할 두 가지 문제:
물론 내가 보여드린 것(TMTOWTDI) 외에 내부 공백을 처리하는 또 다른 방법이 있습니다. 예를 들어 Raku의
:s
"sigspace" 정규식 부사를 사용하는 것입니다.입력 텍스트는 더 짧은 코드를 사용하거나 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