Como extrair caracteres entre o primeiro e o segundo sublinhados dos nomes de arquivos e contar esses arquivos na pasta Linux?

Como extrair caracteres entre o primeiro e o segundo sublinhados dos nomes de arquivos e contar esses arquivos na pasta Linux?

Gostaria de extrair caracteres entre o primeiro e o segundo sublinhados dos nomes de arquivos em uma pasta e contar esses tipos de arquivos presentes nela.

A pasta contém arquivos em um formato específico, como:

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

E assim por diante…

A saída do script deve me dar um resultado como:

ABC 3
DEF 3
MNO 2

Responder1

ls | cut -d_ -f2 | sort | uniq -c

Responder2

Você pode fazer isso da maneira clássica *nix, agrupando pequenos comandos. Primeiro encontre os arquivos de seu interesse, para isso você pode usar shellglobulando:

for i in *_*_*; do echo "$i"; done

Esse comando imprimirá todos os arquivos do diretório atual cujo nome contém dois sublinhados. Para extrair a string entre esses sublinhados, você poderia usarcut, dizendo para usar _como delimitador de campo e imprimir o segundo campo:

cut -d '_' -f 2

Canalizar o primeiro comando até o segundo imprimirá as strings de seu interesse, mas também imprimirá uma linha vazia para os casos em que não há nenhum caractere entre os sublinhados ( foo__barpor exemplo). Você pode filtrá-los usando grep .which imprimirá apenas linhas que contenham pelo menos um caractere (incluindo espaços em branco). Finalmente, você pode contar passando a saída porsorteuniq -c.

Juntar tudo dá a você:

$ for i in *_*_*; do echo "$i" | cut -d '_' -f 2 ; done | 
   grep . | sort | uniq -c

  3 ABC
  2 DEF
  1 MNO

Se você realmente deseja que o número esteja do outro lado, você pode usar 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

Responder3

Aqui está uma maneira de fazer o trabalho usando Perl.

perl -aE '/^[^_]+_\K[^_]+/ && $h{$&}++}{say$_," ",$h{$_} for sort keys %h' file
ABC 3
DEF 3
MNO 2

Explicação:

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

informação relacionada