Извлечение подстроки в Bash
Проблема: Извлечение пятицифрового числа из названия файла
У меня есть название файла в формате <code>someletters_12345_moreletters.ext</code>
, и мне нужно извлечь пятизначную последовательность цифр и сохранить её в переменной.
Чтобы уточнить задачу: у меня есть название файла, состоящее из произвольного количества символов, затем располагается пятизначная последовательность цифр, окружённая одинарным знаком подчеркивания с обеих сторон, а затем идет еще одна произвольная последовательность символов. Мне необходимо извлечь это пятизначное число и сохранить его в переменной.
Я буду очень признателен за описание различных способов, с помощью которых это можно реализовать.
5 ответ(ов)
Попробуйте использовать команду cut -c startIndx-stopIndx
. Эта команда позволяет извлекать определенные символы из строк, указывая диапазон индексов. Например, если вы хотите получить символы с 5 по 10, используйте cut -c 5-10
. Убедитесь, что индексы начинаются с 1.
Ответ на ваш вопрос о том, как извлечь число из имени файла, может быть представлен несколькими способами, в зависимости от вашего конкретного случая. Вот несколько универсальных решений:
- Извлечение первого пятизначного числа из имени файла:
number=$(echo "$filename" | egrep -o '[[:digit:]]{5}' | head -n1)
Этот подход находит первую последовательность из пяти цифр.
- Извлечение части переменной по заданным смещениям и длине:
number="${filename:offset:length}"
Этот метод подходит, если вы знаете точное положение числа в строке.
- Если ваше имя файла всегда имеет формат
stuff_digits_...
, вы можете использоватьawk
:
number=$(echo "$filename" | awk -F _ '{ print $2 }')
Здесь мы разделяем строку по символу подчеркивания (_
) и выводим второй элемент, который и будет вашим числом.
- Удаление всего, кроме цифр:
number=$(echo "$filename" | tr -cd '[[:digit:]]')
Этот способ убирает все символы, кроме цифр, из строки.
Выберите наиболее подходящий метод в зависимости от структуры ваших имен файлов!
Если кто-то хочет получить более детальную информацию, вы также можете поискать это в man bash
, сделав следующее:
$ man bash [нажмите клавишу Enter]
/substring [нажмите клавишу Enter]
[нажмите клавишу "n"]
[нажмите клавишу "n"]
[нажмите клавишу "n"]
[нажмите клавишу "n"]
Результат будет следующим:
${parameter:offset}
${parameter:offset:length}
Расширение подстроки. Расширяется до максимум length символов
параметра, начиная с символа, указанного offset. Если
length опущен, расширяется до подстроки параметра, начинающейся
с символа, указанного offset. length и offset являются
арифметическими выражениями (см. НИЖЕ АРИФМЕТИЧЕСКОЕ
ВЫЧИСЛЕНИЕ). Если offset оценивается как число меньше нуля,
значение используется как смещение от конца значения параметра.
Арифметические выражения, начинающиеся с -, должны
отделяться пробелом от предшествующего :, чтобы их не
перепутали с расширением USE DEFAULT VALUES. Если length
оценивается как число меньше нуля, и параметр не равен @ и не
является индексированным или ассоциативным массивом,
он интерпретируется как смещение от конца значения параметра,
а не как количество символов, и расширение — это символы между
двумя смещениями. Если параметр равен @, результат — это
length позиционных параметров, начиная с offset. Если параметр
является названием индексированного массива с индексом @ или *,
результат — length элементов массива, начиная с
${parameter[offset]}. Отрицательное смещение принимается относительно
одного, превышающего максимальный индекс указанного массива.
Применение расширения подстроки к ассоциативному массиву дает
неопределенные результаты. Обратите внимание, что отрицательное
смещение должно быть отделено от двоеточия хотя бы одним пробелом,
чтобы избежать путаницы с расширением :- . Индексация подстрок
осуществляется с нуля, если используются позиционные параметры,
в противном случае индексация начинается с 1 по умолчанию.
Если offset равен 0 и используются позиционные параметры,
к списку добавляется $0.
Я удивлён, что не упомянули это решение на чистом Bash:
a="someletters_12345_moreletters.ext"
IFS="_"
set -- $a
echo $2
# выводит 12345
Вероятно, вы захотите восстановить значение IFS до его предыдущего состояния или выполнить unset IFS
после использования!
В дополнение к ответу jor (который не работает для меня):
substring=$(expr "$filename" : '.*_\([^_]*\)_.*')
Этот код использует команду expr
для извлечения подстроки из переменной filename
. Он ищет часть строки между последним символом подчеркивания _
и следующим символом _
. Однако, обратите внимание, что такой подход может не сработать в некоторых случаях, если имя файла не соответствует ожидаемому шаблону.
Если вам нужно более надежное решение, вы можете попробовать использовать команду sed
или awk
. Например, используя sed
, вы можете сделать так:
substring=$(echo "$filename" | sed -E 's/.*_([^_]*)_.*/\1/')
Это регулярное выражение будет извлекать все, что находится между последними двумя символами _
. Убедитесь, что ваше имя файла соответствует этому шаблону.
Как проверить, содержит ли строка подстроку в Bash
Есть ли в Python метод подстроки 'contains' для строк?
Как выводить команды оболочки по мере их выполнения
Как проверить, содержит ли строка подстроку?
Как указать приватный SSH-ключ для выполнения команды shell в Git?