
У меня есть имя файла по этой модели:
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, …) имеют некоторые базовые возможности для обработки строк как часть подстановки переменных. См., например,руководство по эксплуатациив разделе «Расширение параметров». Вы можете удалить самый короткий/длинный префикс/суффикс, соответствующий шаблону.
Вам нужна последняя последовательность цифр в имени файла, поэтому:
- Определите нечисловой суффикс, удалив все до последней цифры.
- Удалите этот суффикс.
- Уберите все до последней нецифровой части.
filename=1.raw_bank_details_211.trg
suffix="${filename##*[0-9]}"
number="${filename%"$suffix"}"
number="${number##*[!-0-9]}"
¹ За исключением некоторых оболочек Bourne, не поддерживающих POSIX, но они вас не интересуют.