Me gustaría extraer caracteres entre el primer y segundo guión bajo de los nombres de archivos en una carpeta y contar ese tipo de archivos presentes en ella.
La carpeta contiene archivos en un formato particular 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
Etcétera…
La salida del script debería darme un resultado como:
ABC 3
DEF 3
MNO 2
Respuesta1
ls | cut -d_ -f2 | sort | uniq -c
Respuesta2
Puedes hacer esto de la forma clásica *nix, encadenando pequeños comandos. Primero, busque los archivos de interés, para ello puede usar shellglobo:
for i in *_*_*; do echo "$i"; done
Ese comando imprimirá todos los archivos en el directorio actual cuyo nombre contenga dos guiones bajos. Para extraer la cadena entre esos guiones bajos, puedes usarcut
, diciéndole que lo use _
como delimitador de campo e imprima el segundo campo:
cut -d '_' -f 2
Pasar el primer comando al segundo imprimirá las cadenas que le interesan, pero también imprimirá una línea vacía para aquellos casos en los que no hay ningún carácter entre los guiones bajos ( foo__bar
por ejemplo). Puede filtrarlos usando grep .
el cual solo imprimirá líneas que contengan al menos un carácter (incluido el espacio en blanco). Finalmente, puedes contar pasando la salida porsort
yuniq -c
.
Poniéndolo todo junto te da:
$ for i in *_*_*; do echo "$i" | cut -d '_' -f 2 ; done |
grep . | sort | uniq -c
3 ABC
2 DEF
1 MNO
Si realmente quieres que el número esté en el otro lado, puedes 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
Respuesta3
Aquí hay una manera de hacer el trabajo usando Perl.
perl -aE '/^[^_]+_\K[^_]+/ && $h{$&}++}{say$_," ",$h{$_} for sort keys %h' file
ABC 3
DEF 3
MNO 2
Explicación:
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