フォルダー内のファイル名の最初のアンダースコアと 2 番目のアンダースコアの間の文字を抽出し、フォルダー内に存在するそのような種類のファイルをカウントしたいと思います。
フォルダーには、次のような特定の形式のファイルが含まれています。
2305195303310_ABC_A08_1378408840043.hl7
2305195303310_ABC_A08_1378408840043.hl7
Q37984932T467566261_DEF_R03_1378825633215.hl7
37982442T467537201_DEF_R03_1378823455384.hl7
37982442T467537201_MNO_R03_1378823455384.hl7
2305195303310_ABC_A08_1378408840053.hl7
Q37984932T467566261_DEF_R03_1378825633215.hl7
37982442T467537201_MNO_R03_1378823455384.hl7
等々…
スクリプトの出力は次のようになります:
ABC 3
DEF 3
MNO 2
答え1
ls | cut -d_ -f2 | sort | uniq -c
答え2
これは、*nixの古典的な方法で、小さなコマンドをつなげて実行できます。まず、興味のあるファイルを見つけます。これにはシェルを使用できます。グロビング:
for i in *_*_*; do echo "$i"; done
このコマンドは、現在のディレクトリにあるファイル名に2つのアンダースコアを含むすべてのファイルを出力します。アンダースコア間の文字列を抽出するには、次のようにします。cut
_
をフィールド区切り文字として使用し、2 番目のフィールドを印刷するように指示します。
cut -d '_' -f 2
最初のコマンドを2番目のコマンドにパイプすると、必要な文字列が出力されますが、アンダースコアの間に文字がない場合(foo__bar
たとえば)には空行も出力されます。これをフィルターして、grep .
少なくとも1文字(空白を含む)を含む行のみを出力できます。最後に、出力を渡すことでカウントできます。sort
そしてuniq -c
。
これらすべてをまとめると次のようになります。
$ for i in *_*_*; do echo "$i" | cut -d '_' -f 2 ; done |
grep . | sort | uniq -c
3 ABC
2 DEF
1 MNO
本当に反対側に数字を表示したい場合は、次のようにしますawk
。
$ for i in *_*_*; do echo "$i" | cut -d '_' -f 2 ; done |
grep . | sort | uniq -c | awk '{print $2,$1}'
ABC 3
DEF 2
MNO 1
答え3
Perl を使用して作業を実行する方法を次に示します。
perl -aE '/^[^_]+_\K[^_]+/ && $h{$&}++}{say$_," ",$h{$_} for sort keys %h' file
ABC 3
DEF 3
MNO 2
説明:
perl -aE # invoque Perl compiler with autosplit lines
/^[^_]+_\K[^_]+/ # match non _ characters after the first _
&& # execute the next command if a match is found
$h{$&}++} # increment a counter for each match founded
{say$_," ",$h{$_} # finally print each match and the counter associated
for sort keys %h # for each sorted matches