2014-02-11 2 views
1

Я пытаюсь использовать СЭД в следующем-иш образом:СЭД с произвольными переменными, которые могут содержать косую черту

VAR=`echo $STRING | sed s/$TOKEN/$REPLACEMENT/` 

К сожалению, я пришел на случай, когда $ ЗАМЕНА может возможно содержать косую черту. Это приводит к тому, Баш жаловаться, так как она (оболочка) потенциально расширяет его на что-то вроде этого:

#given $VAR=I like bananas, $TOKEN=bananas, and $REPLACEMENT=apples/oranges 
VAR=`echo I like bananas | sed s/bananas/apples/oranges/` 

Так что теперь СЭД дается неверный аргумент с слишком много/'s. Есть ли хороший способ справиться с этим?

+0

Вы должны заменить старые и обратные устарел тиков с скобки '$ (...)' пример: 'VAR = $ (эхо $ STRING | sed s/$ TOKEN/$ REPLACEMENT /) ' – Jotne

+0

Возможный дубликат команды [sed: как использовать переменную] (http://stackoverflow.com/questions/19151954/sed-command-how-to-use- переменная) – devnull

+0

Это хуже, чем это. Если $ TOKEN содержит метасимволы RE ('.',' * 'и т. Д.), То sed также оценит их. Это то, что вы хотите? –

ответ

3

Вы можете использовать любой разделитель вам нравится. "s!$TOKEN!$REPLACEMENT!" и "s%$TOKEN%$REPLACEMENT%" являются популярными альтернативами.

Конечно, в общем случае, если вход может содержать любые символы, вы вернетесь к квадрату. Вы можете переключиться на язык, который не смешивает код и данные так легкомысленно ... включая собственно оболочку;

echo "${VAR/$TOKEN/$REPLACEMENT}" 

(.. Это расширение Bash, хотя он доступен в некоторых других оболочек, но не в классической оболочке Bourne)

+0

Другим хорошим вариантом является непечатаемые символы управления ascii, которые вряд ли появятся в строках: 'printf -v foo 's \ x01% s \ x01% s \ x01'" searchstring "" replacsestring "; echo "$ string" | sed -e "$ foo" ' –

+1

@thatotherguy интригующая идея, но я не решаюсь рекомендовать это, так как она обязательно ломается на различные реализации' sed' там. – tripleee

+0

Я сомневаюсь. Это будет нарушать POSIX и будет сложнее реализовать на C, чем просто разрешить его. –

0

Вы не можете надежно использовать СЭД для этого, как:

  1. вы обычно не можете найти символ, который гарантированно не будет ни в одном из $ TOKEN или $ строк ЗАМЕНЫ и
  2. SED не может найти строку - она ​​всегда ищет регулярные выражения и , поэтому любые метасимволы RE в $ TOKEN будут оцениваться как таковые, и вы не можете надежно реализовать код, чтобы избежать их (несмотря на то, что многие люди пытались).

Так, просто использовать AWK:

VAR=$(echo "$STRING" | awk -v t="$TOKEN" -v r="$REPLACEMENT" 'idx=index($0,t) {$0 = substr($0,1,idx-1) r substr($0,idx+length(t))} 1') 

Это будет работать для абсолютно любого характера в любом из 3-х строк, за исключением символа новой строки в $ STRING.

Без echo он будет обрабатывать символ новой строки в $ STRING тоже:

VAR=$(awk -v s="$STRING" -v t="$TOKEN" -v r="$REPLACEMENT" ' 
BEGIN { 
    if (idx = index(s,t)) 
     s = substr(s,1,idx-1) r substr(s,idx+length(t)) 
    print s 
}') 
Смежные вопросы