Извлечение числа из имени файла

Извлечение числа из имени файла

У меня есть имя файла по этой модели:

 1.raw_bank_details_211.trg
 2.raw_bank_details_222.trg

Мне нужно использовать cutкоманду в Unix и вырезать указанную выше строку, чтобы получить 211 из 222строк и вывести значение.

Я уже использовал grep grep -o -E '[0-9]+', мне нужна альтернатива.

решение1

Лучше использовать стандартный инструмент обработки текста вместо такого примитивного инструмента, как cut.

Вот несколько способов:


С помощью awk, получаем _или .разделенное предпоследнее поле:

awk -F '[_.]' '{print $(NF-1)}' file.txt

grepс PCRE ( -P):

grep -Po '\d+(?=[^_]*$)' file.txt
  • -oполучает только соответствующую часть

  • \d+соответствует одной или нескольким цифрам

  • Положительный просмотр вперед нулевой ширины (?=[^_]*$)гарантирует, что _до конца строки не будет продолжено ни одного символа.


С sed:

sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
  • .*_соответствует всему до последнего_

  • ([[:digit:]]+)сопоставляет требуемые цифры и помещает в захваченную группу

  • .*соответствует остальным

  • При замене \1используется только захваченная группа, ,


С perl, та же логика sed:

perl -pe 's/.*_(\d+).*/$1/' file.txt 

Если вам необходимо использовать cut, сделайте это в два этапа, сначала получите _отделенное 4-е поле, а затем получите .отделенное 1-е поле:

cut -d_ -f4 file.txt | cut -d. -f1

Это не рекомендуется, поскольку для этого требуется жестко закодировать номера полей.


Если бы это была строка, я бы сделал это с помощью расширения параметров оболочки:

% str='1.raw_bank_details_211.trg'

% str=${str##*_} 

% echo "${str%%.*}"
211

Вы все еще можете использовать whileконструкцию и взять каждую строку в переменную и сделать это, но это будет медленно для большого файла. Также альтернативно вы можете использовать _.как IFSи получить жестко закодированное поле (например cut) вместо этого, если хотите.


Пример:

% cat file.txt                          
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg

% awk -F '[_.]' '{print $(NF-1)}' file.txt
211
222

% grep -Po '\d+(?=[^_]*$)' file.txt         
211
222

% sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
211
222

% perl -pe 's/.*_(\d+).*/$1/' file.txt 
211
222

% cut -d_ -f4 file.txt | cut -d. -f1
211
222

решение2

cutнеподходящий инструмент для этого. Для обработки коротких строк, таких как имена файлов, используйте возможности оболочки для обработки строк, когда это возможно. Все оболочки типа sh¹ (sh, dash, bash, ksh, zsh, …) имеют некоторые базовые возможности для обработки строк как часть подстановки переменных. См., например,руководство по эксплуатациив разделе «Расширение параметров». Вы можете удалить самый короткий/длинный префикс/суффикс, соответствующий шаблону.

Вам нужна последняя последовательность цифр в имени файла, поэтому:

  1. Определите нечисловой суффикс, удалив все до последней цифры.
  2. Удалите этот суффикс.
  3. Уберите все до последней нецифровой части.
filename=1.raw_bank_details_211.trg
suffix="${filename##*[0-9]}"
number="${filename%"$suffix"}"
number="${number##*[!-0-9]}"

¹ За исключением некоторых оболочек Bourne, не поддерживающих POSIX, но они вас не интересуют.

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