各列に数字を含む行数を返します。

各列に数字を含む行数を返します。

この質問に対する回答を試しましたが、特定の要件に合わせて調整することはできませんでした。

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

注目すべき2つの問題:

  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

関連情報