Как извлечь 5-значное число из имени файла в Bash?
Дано имя файла в формате someletters_12345_moreleters.ext, как можно извлечь 5-значное число (12345 в этом примере) и сохранить его в переменной?
Я ищу несколько способов выполнения этой задачи в Bash, где имя файла имеет следующий шаблон:
- Последовательность символов (x количество символов)
- Одно подчёркивание
- 5-значное число
- Ещё одно подчёркивание
- Ещё одна последовательность символов (x количество символов)
- Расширение файла
Какие существуют различные методы извлечения 5-значного числа из таких имён файлов в Bash?
Извлечение 5-значного числа из имени файла в Bash
Вы можете извлечь 5-значное число из имен файлов в формате someletters_12345_moreleters.ext с помощью нескольких методов в Bash. Наиболее распространенные подходы включают расширение параметров, регулярные выражения с grep/egrep, awk и sed, каждый из которых имеет разные преимущества с точки зрения простоты, производительности и читаемости.
Содержание
- Методы с использованием расширения параметров
- Использование grep и регулярных выражений
- Решения на основе Awk
- Подход на основе Sed
- Использование команд cut и tr
- Сравнение методов
- Пример полного скрипта
Методы с использованием расширения параметров
Расширение параметров в Bash предоставляет эффективные способы извлечения шаблонов из строк без создания подпроцессов.
Метод 1: Использование подстановки шаблонов
filename="someletters_12345_moreleters.ext"
number="${filename##*_}"
number="${number%%_*}"
echo "$number" # Вывод: 12345
Как это работает:
${filename##*_}удаляет все до последнего символа подчеркивания включительно${number%%_*}удаляет все от первого символа подчеркивания до конца- Этот метод не проверяет, что это именно 5 цифр, но извлекает среднюю часть
Метод 2: Использование сопоставления с регулярными выражениями в Bash
filename="someletters_12345_moreleters.ext"
if [[ $filename =~ ^[^_]*_([0-9]{5})_[^_]*\. ]]; then
number="${BASH_REMATCH[1]}"
echo "$number" # Вывод: 12345
fi
Как это работает:
^[^_]*_соответствует всему до первого символа подчеркивания([0-9]{5})захватывает ровно 5 цифр в группу_[^_]*\.соответствует от второго символа подчеркивания до точки${BASH_REMATCH[1]}содержит захваченную группу
Использование grep и регулярных выражений
Семейство инструментов grep отлично подходит для сопоставления с шаблонами с использованием регулярных выражений.
Метод 3: Использование egrep с закрепленным шаблоном
filename="someletters_12345_moreleters.ext"
number=$(echo "$filename" | egrep -o '[0-9]{5}')
echo "$number" # Вывод: 12345
Как это работает:
egrep -oвыводит только совпавшую часть[0-9]{5}соответствует ровно 5 последовательным цифрам- Этот метод прост, но может соответствовать нескольким 5-значным последовательностям, если они существуют
Метод 4: Использование grep с контекстным сопоставлением
filename="someletters_12345_moreleters.ext"
number=$(echo "$filename" | grep -oP '(?<=_)[0-9]{5}(?=_)')
echo "$number" # Вывод: 12345
Как это работает:
-Pвключает регулярные выражения, совместимые с Perl(?<=_)- положительный просмотр назад для символа подчеркивания(?=_)- положительный просмотр вперед для символа подчеркивания- Это гарантирует, что 5-значное число окружено символами подчеркивания
Решения на основе Awk
Awk мощен для обработки текста и может справляться со сложным сопоставлением с шаблонами.
Метод 5: Использование awk с разделением полей
filename="someletters_12345_moreleters.ext"
number=$(echo "$filename" | awk -F'_' '{print $2}')
echo "$number" # Вывод: 12345
Как это работает:
-F'_'устанавливает символ подчеркивания в качестве разделителя полейprint $2выводит второе поле (число)- Просто, но предполагает, что число всегда является вторым полем
Метод 6: Использование awk с сопоставлением по регулярным выражениям
filename="someletters_12345_moreleters.ext"
number=$(echo "$filename" | awk '{match($0, /_[0-9]{5}_/, arr); print substr(arr[0], 2, 5)}')
echo "$number" # Вывод: 12345
Как это работает:
match()находит шаблон и сохраняет его в массивеarrsubstr()извлекает 5 цифр, пропуская первый символ подчеркивания- Более гибко, чем простое разделение полей
Подход на основе Sed
Sed (потоковый редактор) может извлекать шаблоны с помощью команд подстановки.
Метод 7: Использование sed с подстановкой шаблонов
filename="someletters_12345_moreleters.ext"
number=$(echo "$filename" | sed -n 's/.*_\([0-9]\{5\}\)_.*\.ext/\1/p')
echo "$number" # Вывод: 12345
Как это работает:
-nподавляет автоматический выводs/.*_\([0-9]\{5\}\)_.*\.ext/\1/pподставляет и выводит захваченную группу\{5\}эквивалентно{5}в расширенных регулярных выражениях- Шаблон явно соответствует расширению
.ext
Использование команд cut и tr
Эти традиционные инструменты Unix можно комбинировать для извлечения чисел.
Метод 8: Использование комбинации cut и tr
filename="someletters_12345_moreleters.ext"
number=$(echo "$filename" | cut -d'_' -f2 | tr -d '.ext')
echo "$number" # Вывод: 12345
Как это работает:
cut -d'_' -f2извлекает второе поле (после первого символа подчеркивания)tr -d '.ext'удаляет символы расширения- Просто, но менее надежно для переменных расширений
Метод 9: Использование tr для удаления нецифровых символов
filename="someletters_12345_moreleters.ext"
number=$(echo "$filename" | tr -c -d '0-9' | grep -o '.....')
echo "$number" # Вывод: 12345
Как это работает:
tr -c -d '0-9'оставляет только цифры, удаляя все остальные символыgrep -o '.....'извлекает ровно 5 символов- Работает, но может дать сбой, если существует несколько цифровых последовательностей
Сравнение методов
| Метод | Производительность | Читаемость | Надежность | Зависимости |
|---|---|---|---|---|
| Расширение параметров | Отличная | Хорошая | Умеренная | Нет (встроено в Bash) |
| grep/egrep | Хорошая | Отличная | Хорошая | grep/egrep |
| Awk | Умеренная | Хорошая | Отличная | awk |
| Sed | Умеренная | Умеренная | Хорошая | sed |
| cut/tr | Отличная | Хорошая | Плохая | cut, tr |
| Регулярные выражения Bash | Отличная | Хорошая | Отличная | Bash 4+ |
Рекомендации:
- Для чистых Bash-сред: используйте расширение параметров или регулярные выражения Bash
- Для максимальной гибкости: используйте awk с регулярными выражениями
- Для простых случаев: grep с флагом
-o - Для критически важных к производительности скриптов: расширение параметров
Пример полного скрипта
Вот полный скрипт, демонстрирующий несколько подходов:
#!/bin/bash
# Функция для извлечения 5-значного числа с использованием разных методов
extract_number_param() {
local filename="$1"
local number="${filename##*_}"
number="${number%%_*}"
echo "$number"
}
extract_number_grep() {
local filename="$1"
echo "$filename" | grep -oP '(?<=_)[0-9]{5}(?=_)'
}
extract_number_awk() {
local filename="$1"
echo "$filename" | awk -F'_' '{print $2}'
}
extract_number_bash_regex() {
local filename="$1"
if [[ $filename =~ ^[^_]*_([0-9]{5})_[^_]*\. ]]; then
echo "${BASH_REMATCH[1]}"
fi
}
# Тест с примером имени файла
filename="someletters_12345_moreleters.ext"
echo "Исходное имя файла: $filename"
echo "Расширение параметров: $(extract_number_param "$filename")"
echo "grep с просмотром вокруг: $(extract_number_grep "$filename")"
echo "Разделение полей awk: $(extract_number_awk "$filename")"
echo "Регулярные выражения Bash: $(extract_number_bash_regex "$filename")"
# Обработка нескольких файлов в каталоге
echo -e "\nОбработка файлов в текущем каталоге:"
for file in *_*.ext; do
if [[ -f "$file" ]]; then
num=$(extract_number_bash_regex "$file")
if [[ $num =~ ^[0-9]{5}$ ]]; then
echo "Файл: $file -> Число: $num"
fi
fi
done
Этот скрипт предоставляет четыре разных метода и демонстрирует, как применить их как к отдельным именам файлов, так и к пакетной обработке файлов в каталоге. Метод с регулярными выражениями Bash включает проверку для гарантии извлечения ровно 5 цифр.
Источники
- Stack Overflow - Извлечение чисел из имени файла
- Unix & Linux Stack Exchange - Извлечение числа из имени файла
- Unix & Linux Stack Exchange - Как извлечь числа из имени файла
- Baeldung - Как найти имена файлов, заканчивающиеся числом в Bash
- Collecting Wisdom - Bash: Как извлечь числа из имени файла
Заключение
Извлечение 5-значных чисел из имен файлов в Bash можно выполнить с помощью нескольких подходов, каждый из которых имеет свои преимущества:
- Расширение параметров обеспечивает лучшую производительность и не требует внешних зависимостей
- Сопоставление с регулярными выражениями Bash обеспечивает отличную надежность с встроенной проверкой шаблона
- grep с просмотром вокруг предоставляет наиболее читаемое решение для сложных шаблонов
- awk предлагает наибольшую гибкость для расширенной обработки текста
- sed полезен для шаблонов, включающих подстановки и захваты
Для конкретного шаблона someletters_12345_moreleters.ext рекомендуется метод с регулярными выражениями Bash [[ $filename =~ ^[^_]*_([0-9]{5})_[^_]*\. ]], так как он одновременно производителен и проверяет точный формат из 5 цифр. Для пакетной обработки объедините этот метод с простым циклом по файлам в вашем каталоге.
Выберите метод, который лучше всего соответствует вашему конкретному случаю использования, учитывая такие факторы, как требования к производительности, потребности в читаемости и сложность шаблонов имен файлов.