Как извлечь символы между первым и вторым подчеркиванием имен файлов и подсчитать количество таких файлов в папке Linux?

Как извлечь символы между первым и вторым подчеркиванием имен файлов и подсчитать количество таких файлов в папке Linux?

Мне бы хотелось извлечь символы между первым и вторым подчеркиванием имен файлов в папке и подсчитать количество файлов такого типа, присутствующих в ней.

Папка содержит файлы в определенном формате, например:

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, объединяя небольшие команды вместе. Сначала найдите интересующие вас файлы, для этого вы можете использовать shellподстановка:

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

Эта команда выведет все файлы в текущем каталоге, имя которых содержит два подчеркивания. Чтобы извлечь строку между этими подчеркиваниями, вы можете использоватьcut, сообщая ему, что нужно использовать его _в качестве разделителя полей и вывести второе поле:

cut -d '_' -f 2

Прохождение первой команды через вторую выведет интересующие вас строки, но также выведет пустую строку в тех случаях, когда между подчеркиваниями нет символа ( foo__barнапример). Вы можете отфильтровать их, используя , grep .который выведет только строки, содержащие хотя бы один символ (включая пробел). Наконец, вы можете подсчитать, пропустив вывод через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

Связанный контент