Другое

Bash: Удаление фиксированного префикса и суффикса из строки

Узнайте, как удалить фиксированный префикс и суффикс из строк в Bash, используя расширение параметров. Пошаговый пример, лучшие практики и альтернативы.

Как удалить фиксированный префикс и суффикс из строки в Bash?
Например, имея:

  • string="hello-world"
  • prefix="hell"
  • suffix="ld"

Как извлечь среднюю часть строки, чтобы получить "o-wor"?

Чтобы удалить фиксированный префикс и суффикс из строки в Bash, можно использовать расширение параметров с двумя последовательными операциями: сначала удалить префикс с помощью ${string#pattern}, затем удалить суффикс из результата с помощью ${result%suffix}. Для вашего примера с string="hello-world", prefix="hell", и suffix="ld", вы выполните foo=${string#"$prefix"} затем foo=${foo%"$suffix"}, что вернет "o-wor".

Содержание

Понимание основ расширения параметров

Расширение параметров Bash — мощная функция, позволяющая манипулировать переменными и строками непосредственно в оболочке без создания внешних процессов. Согласно Stack Overflow, этот подход обычно является самым быстрым способом работы с переменными.

Ключевые операторы для удаления подстрок:

  • ${var#pattern} – удаляет самый короткий совпадающий префикс
  • ${var##pattern} – удаляет самый длинный совпадающий префикс
  • ${var%pattern} – удаляет самый короткий совпадающий суффикс
  • ${var%%pattern} – удаляет самый длинный совпадающий суффикс

Как отмечено в статье Linux Journal, можно запомнить, какой оператор делает что, по их расположению на клавиатуре — # находится раньше %, так же как префиксы находятся раньше суффиксов в строке.

Важно: всегда заключайте шаблоны в двойные кавычки ("${pattern}"), когда работаете с переменными, чтобы сохранить пробелы и предотвратить разбиение на слова.

Удаление префикса и суффикса двумя операциями

Чтобы удалить как префикс, так и суффикс из строки, необходимо выполнить два отдельных оператора расширения параметров, потому что, как объясняет один из ответов на Stack Overflow, «нельзя удалить и префикс, и суффикс в одном операторе».

Вот пошаговый процесс для вашего примера:

bash
string="hello-world"
prefix="hell"
suffix="ld"

# Сначала удаляем префикс
foo=${string#"$prefix"}    # Удаляет "hell" → оставляет "o-world"

# Затем удаляем суффикс из результата
foo=${foo%"$suffix"}       # Удаляет "ld" → оставляет "o-wor"

echo "$foo"                # Вывод: o-wor

Этот двухшаговый подход надёжно работает в большинстве случаев. Первый оператор ${string#"$prefix"} удаляет самый короткий совпадающий префикс в начале строки, а второй оператор ${foo%"$suffix"} удаляет самый короткий совпадающий суффикс в конце изменённой строки.

Правила сопоставления шаблонов в Bash

Bash использует правила сопоставления шаблонов, похожие на подстановку файлов при работе с globbing, при выполнении расширения параметров. Согласно Advanced Bash Scripting Guide, шаблоны разворачиваются и сопоставляются согласно определённым правилам.

Как работает сопоставление:

  • * соответствует любым символам (включая отсутствие символов)
  • ? соответствует любому одиночному символу
  • [abc] соответствует любому символу из набора
  • [!abc] соответствует любому символу, не входящему в набор

Например, если у вас:

bash
string="prefix-mid-suffix"
prefix="pre*"
suffix="*fix"

Операции будут:

bash
result=${string#"$prefix"}    # Удаляет "pre*" → "mid-suffix"
result=${result%"$suffix"}    # Удаляет "*fix" → "mid-suffix"

Как объясняет Stack Abuse, оператор %% удаляет самый длинный совпадающий шаблон с конца, а оператор # удаляет самый короткий совпадающий шаблон с начала.

Практические примеры и варианты использования

Обработка расширений файлов и путей

Один из распространённых вариантов — обработка путей файлов и расширений:

bash
filename="document1-abc-123.txt"
extension=".txt"
prefix="document"

# Удаляем расширение
basename=${filename%"$extension"}  # document1-abc-123
# Удаляем префикс
result=${basename#"$prefix"}       # 1-abc-123

Обработка URL

bash
url="https://www.example.com/page/path"
protocol="https://"
tld=".com"

# Удаляем протокол
domain=${url#"$protocol"}    # www.example.com/page/path
# Удаляем TLD из домена
domain=${domain%"$tld"}      # www.example.com/page

Реализация функции

Можно создать переиспользуемую функцию, как показано в Bash Commands:

bash
remove_prefix_suffix() {
    local string="$1"
    local prefix="$2"
    local suffix="$3"
    
    # Удаляем префикс
    local result="${string#"$prefix"}"
    # Удаляем суффикс
    result="${result%"$suffix"}"
    
    echo "$result"
}

# Использование
string="hello-world"
prefix="hell"
suffix="ld"
result=$(remove_prefix_suffix "$string" "$prefix" "$suffix")
echo "$result"  # Вывод: o-wor

Распространённые ошибки и лучшие практики

Кавычки вокруг шаблонов

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

bash
# Неправильно (провалится с пробелами или специальными символами)
foo=${string#$prefix}

# Правильно
foo=${string#"$prefix"}

Порядок операций

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

bash
# Неправильный подход
string="hello-world"
prefix="hell"
suffix="ld"

# Удаляем суффикс первым
wrong=${string%"$suffix"}   # hello-wor
wrong=${wrong#"$prefix"}    # o-wor (работает в этом случае, но ненадёжно)

# Правильный подход (всегда префикс сначала)
correct=${string#"$prefix"}  # o-world
correct=${correct%"$suffix"} # o-wor (надёжно)

Обработка множественных совпадений

Если шаблоны могут встречаться несколько раз, используйте «жадные» версии:

bash
string="abc123def123ghi"
prefix="abc"
suffix="ghi"

# Стандартные версии (удаляют самый короткий матч)
result=${string#"$prefix"}  # 123def123ghi
result=${result%"$suffix"}  # 123def123

# Жадные версии (удаляют самый длинный матч)  
result=${string##"$prefix"} # 123def123ghi (то же, что выше)
result=${result%%"$suffix"} # 123def123 (то же, что выше)

Обработка ошибок

Рассмотрите возможность добавления обработки ошибок для случаев, когда шаблоны не совпадают:

bash
remove_prefix_suffix() {
    local string="$1"
    local prefix="$2" 
    local suffix="$3"
    
    # Проверяем наличие шаблонов перед удалением
    if [[ "$string" == "$prefix"* ]]; then
        string="${string#"$prefix"}"
    fi
    
    if [[ "$string" == *"$suffix" ]]; then
        string="${string%"$suffix"}"
    fi
    
    echo "$string"
}

Альтернативные методы и инструменты

Использование sed

Хотя расширение параметров предпочтительнее, можно также использовать sed для более сложных шаблонов:

bash
string="hello-world"
prefix="hell"
suffix="ld"

# Используем sed
result=$(echo "$string" | sed "s/^$prefix//" | sed "s/$suffix$//")
echo "$result"  # Вывод: o-wor

Однако, как отмечает CopyProgramming, расширение параметров обычно быстрее, так как избегает создания внешних процессов.

Использование cut

Для простого удаления по количеству символов (не по шаблону) можно использовать cut:

bash
string="hello-world"
prefix_length=4  # "hell" имеет 4 символа
suffix_length=2  # "ld" имеет 2 символа

# Вычисляем начальную и конечную позиции
start=$((prefix_length + 1))
total_length=${#string}
end=$((total_length - suffix_length))

# Извлекаем подстроку
result=${string:$start:$end}
echo "$result"  # Вывод: o-wor

Использование ${string:offset:length}

Для извлечения подстроки по позициям (когда известны точные позиции):

bash
string="hello-world"

# Извлекаем с позиции 4 (0‑based), длиной 5
result=${string:4:5}  # o-wor

Как объясняет SQLPey, этот подход «избегает создания внешних процессов и обычно является самым быстрым способом работы с переменными».

Заключение

Удаление фиксированного префикса и суффикса из строки в Bash эффективно достигается с помощью расширения параметров двумя последовательными операциями. Самый надёжный метод — сначала удалить префикс с помощью ${string#"$prefix"}, а затем удалить суффикс из результата с помощью ${result%"$suffix"}. Этот подход позволяет извлечь «o-wor» из «hello-world», удалив «hell» и «ld».

Ключевые выводы:

  • Всегда используйте двойные кавычки вокруг шаблонов, чтобы корректно обрабатывать специальные символы.
  • Удаляйте префикс первым, затем суффикс для стабильных результатов.
  • Расширение параметров быстрее, чем внешние инструменты вроде sed или cut, для простых операций.
  • Рассмотрите создание переиспользуемых функций для общих задач обработки строк.
  • Обрабатывайте крайние случаи, когда шаблоны могут не совпадать или встречаться несколько раз.

Для более сложных задач обработки строк изучите полный набор возможностей расширения параметров Bash, описанный в Advanced Bash Scripting Guide и документации Bash.

Источники

  1. Stack Overflow – Remove a fixed prefix/suffix from a string in Bash
  2. Unix Stack Exchange – Pattern match both suffix and prefix in shell script
  3. Linux Journal – Bash Parameter Expansion
  4. Advanced Bash Scripting Guide – Parameter Substitution
  5. Stack Abuse – Guide to Parameter Expansion in Bash
  6. XModulo – How to manipulate strings in bash
  7. SQLPey – Shell Scripting: Multiple Methods to Extract Substring
  8. CopyProgramming – Bash: Eliminating a Constant Prefix/Suffix from a Bash String
Авторы
Проверено модерацией
Модерация