Удалите фиксированный префикс/суффикс из строки в Bash

В моем bash script у меня есть строка и ее префикс/суффикс. Мне нужно удалить префикс/суффикс из исходной строки.

Например, допустим, что у меня есть следующие значения:

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

Как мне получить следующий результат?

result="o-wor"

Ответ 1

$ foo=${string#"$prefix"}
$ foo=${foo%"$suffix"}
$ echo "${foo}"
o-wor

Ответ 2

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

$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor

В команде sed символ ^ соответствует тексту, начинающемуся с $prefix, а завершающий $ соответствует тексту, заканчивающемуся на $suffix.

Адриан Фрюхвирт делает несколько замечательных замечаний в комментариях ниже, но sed для этой цели может быть очень полезен. Тот факт, что содержимое префикса $и $суффикса интерпретируется sed, может быть либо хорошим, либо плохим - пока вы обращаете внимание, вы должны быть в порядке. Красота такова, вы можете сделать что-то вроде этого:

$ prefix='^.*ll'
$ suffix='ld$'
$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor

который может быть тем, что вы хотите, и является более привлекательным и мощным, чем замена переменной bash. Если вы помните, что с великой силой приходит большая ответственность (как говорит Спайдерман), вы должны быть в порядке.

Краткое введение в sed можно найти на http://evc-cit.info/cit052/sed_tutorial.html

Замечание относительно оболочки и ее использование строк:

В приведенном конкретном примере также будет работать следующее:

$ echo $string | sed -e s/^$prefix// -e s/$suffix$//

... но только потому, что:

  • echo не заботится о том, сколько строк в списке аргументов, и
  • В префиксе $и префиксе $suffix нет пробелов

Как правило, правильная практика цитирует строку в командной строке, потому что даже если она содержит пробелы, она будет представлена ​​команде как один аргумент. Мы приводим $prefix и $suffix по той же причине: каждая команда редактирования sed будет передана как одна строка. Мы используем двойные кавычки, потому что они допускают переменную интерполяцию; если бы мы использовали одинарные кавычки, команда sed получила бы буквальный $prefix и $suffix, который, конечно же, не тот, который мы хотели.

Также обратите внимание, что использование одиночных кавычек при настройке переменных prefix и suffix. Мы, конечно, не хотим, чтобы что-то в строках интерпретировалось, поэтому мы приводим их отдельно, поэтому интерполяция не происходит. Опять же, это может быть не нужно в этом примере, но это очень хорошая привычка вступать.

Ответ 3

Знаете ли вы длину вашего префикса и суффикса? В твоем случае:

result=$(echo $string | cut -c5- | rev | cut -c3- | rev)

Или более общий:

result=$(echo $string | cut -c$((${#prefix}+1))- | rev | cut -c$((${#suffix}+1))- | rev)

Но решение от Adrian Frühwirth - это круто! Я не знал об этом!

Ответ 4

Я использую grep для удаления префиксов из путей (которые не обрабатываются с помощью sed):

echo "$input" | grep -oP "^$prefix\K.*"

\K удаляет из совпадения все символы перед ним.

Ответ 5

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

$ #remove "hell" from "hello-world" if "hell" is found at the beginning.
$ prefix_removed_string=${string/#$prefix}

$ #remove "ld" from "o-world" if "ld" is found at the end.
$ suffix_removed_String=${prefix_removed_string/%$suffix}
$ echo $suffix_removed_String
o-wor

Заметки:

ПрефикС# $: добавление # гарантирует, что подстрока "ад" удаляется, только если она найдена в начале. % $ suffix: добавление% гарантирует, что подстрока "ld" удаляется, только если она найдена в конце.

Без них подстроки "ад" и "ld" будут удалены повсюду, даже если они будут найдены посередине.

Ответ 6

Малое и универсальное решение:

expr "$string" : "$prefix\(.*\)$suffix"

Ответ 7

Использование оператора =~:

$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ [[ "$string" =~ ^$prefix(.*)$suffix$ ]] && echo "${BASH_REMATCH[1]}"
o-wor

Ответ 8

Используя @Adrian Frühwirth ответ:

function strip {
    local STRING=${1#$"$2"}
    echo ${STRING%$"$2"}
}

используйте его так

HELLO=":hello:"
HELLO=$(strip "$HELLO" ":")
echo $HELLO # hello

Ответ 9

Я хотел бы использовать группы захвата в регулярном выражении:

$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ set +H # Disables history substitution, can be omitted in scripts.
$ perl -pe "s/${prefix}((?:(?!(${suffix})).)*)${suffix}/\1/" <<< $string
o-wor
$ string1=$string$string
$ perl -pe "s/${prefix}((?:(?!(${suffix})).)*)${suffix}/\1/g" <<< $string1
o-woro-wor

((?:(?!(${suffix})).)*) гарантирует, что содержимое ${suffix} будет исключено из группы захвата. В качестве примера, это строка, эквивалентная [^A-Z]*. В противном случае вы получите:

$ perl -pe "s/${prefix}(.*)${suffix}/\1/g" <<< $string1
o-worldhello-wor