2013-05-18 3 views
258

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

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

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

Как добраться до следующего результата?

result="o-wor" 
+4

Посмотрите [Advanced Bash-Scripting Guide] (http://tldp.org/LDP/abs/html/string-manipulation.html) – tarrsalah

+4

Будьте очень осторожны при подключении к так называемому расширенному руководству по написанию сценариев Bash; он содержит смесь хороших советов и ужасных. – tripleee

ответ

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

Есть также ## и %%, которые удаляют как можно больше, если $ prefix или $ suffix содержат подстановочные знаки. – pts

+12

Есть ли способ объединить два в одной строке? Я попробовал '$ {$ {string # prefix}% suffix}', но он не работает. –

+15

@static_rtti Нет, к сожалению, вы не можете вставлять подстановку параметров так. Я знаю, это позор. –

49

Использование СЭД:

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

В SED команде, ^ символ совпадает с текстом, начиная с $prefix и задней $ матчей текста заканчивая $suffix.

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

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

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

Быстрое введение в СЭД можно найти на http://evc-cit.info/cit052/sed_tutorial.html

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

Для конкретного примера, приведенного, следующий будет работать, а также:

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

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

  1. эхо не все равно, как многие строки в списке аргументов, и
  2. Там нет пробелов в префикса $ и $ суффиксом

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

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

+5

К сожалению , это плохой совет по нескольким причинам: 1) Без кавычек '$ string' подлежит разбиению и глобализации слов. 2) '$ prefix' и' $ suffix' могут содержать выражения, которые 'sed' будет интерпретировать, например. регулярные выражения или символ, используемый как разделитель, который разбивает всю команду. 3) Вызов 'sed' два раза не требуется (вы можете использовать' -e /// '-e' /// ''), и можно также избежать этого. Например, рассмотрите 'string = './*'' И/или 'prefix = '. /'' И увидите, что он прерывается ужасно из-за '1)' и '2)'. –

+0

Замечание: sed может принимать почти что угодно, как разделитель. В моем случае, поскольку я разбирал префикс-директории вне путей, я не мог использовать '/', поэтому вместо этого использовал 'sed 's #^$ prefix ##'. (Fragility: имена файлов не могут содержать ' # '. Поскольку я управляю файлами, мы в безопасности.) – Olie

+0

@Olie Имена файлов могут содержать * любой символ *, кроме символа слэша и нулевого символа, поэтому, если вы не находитесь под контролем, вы не можете считать имя файла не содержащим определенных символов. –

11

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

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

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

10

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

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

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

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

Но solution from Adrian Frühwirth это прохладный путь! Я не знал об этом!

1

Использование @Adrian Frühwirth Ответ:

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

использовать его как этот

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

малого и универсального решения:

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

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

$ string="hello-world" 
$ prefix="hell" 
$ suffix="ld" 
$ [[ $string =~ $prefix(.*)$suffix ]] && echo "${BASH_REMATCH[1]}" 
o-wor 
Смежные вопросы