2015-03-02 19 views
3

substitution commandsed一般形式SED取代是:與用戶指定的替換字符串

s/regexp/replacement/flags 

其中「/」字符可以由任何其它的單個字符被均勻地取代。但是,如果替換字符串由環境變量提供並且可能包含任何可打印字符,那麼如何選擇此分隔符?有沒有簡單的方法來使用bash轉義變量中的分隔符?

這些值來自受信任的管理員,所以安全性並不是我最關心的問題。 (換句話說,請不要回答:「不要這樣做!」)然而,我無法預測替換字符串中需要顯示哪些字符。

回答

1

您可以使用控制字符作爲分隔符的正則表達式也是這樣:

s^Aregexp^Areplacement^Ag 

哪裏^ACTRLv壓在一起

或者使用awk而不用擔心分隔符:

awk -v s="search" -v r="replacement" '{gsub(s, r)} 1' file 
1

這裏不使用sed以下(容易)解決方案。

while read -r string from to wanted 
do 
    echo "in [$string] want replace [$from] to [$to] wanted result: [$wanted]" 
    final=$(echo "$string" | sed "s/$from/$to/") 
    [[ "$final" == "$wanted" ]] && echo OK || echo WRONG 
    echo 
done <<EOF 
=xxx= xxx === ===== 
=abc= abc /// =///= 
=///= /// abc =abc= 
EOF 

什麼打印

in [=xxx=] want replace [xxx] to [===] wanted result: [=====] 
OK 

in [=abc=] want replace [abc] to [///] wanted result: [=///=] 
sed: 1: "s/abc/////": bad flag in substitute command: '/' 
WRONG 

in [=///=] want replace [///] to [abc] wanted result: [=abc=] 
sed: 1: "s/////abc/": bad flag in substitute command: '/' 
WRONG 

無法抗拒:從來沒有做到這一點!(含sed)。 :)

是否有一種直接的方法來逃避 中的分隔符字符變量使用bash?

沒有,因爲你從變量傳遞字符串,你不能輕易逃脫分隔符,因爲在"s/$from/$to/"分離不僅可以在$to一部分,但在$from部分也出現。例如。當你在$from部分逃離分隔符時,它根本不會進行替換,因爲不會找到$from

解決方案:使用其他東西作爲sed

1)使用純慶典。在上面的腳本,而不是sed使用

final=${string//$from/$to} 

2)如果bash的替換是不夠的,用的東西是什麼,你可以通過$from$to作爲變量。

  • 爲@anubhava已經說過,可以用:awk -v f="$from" -v t="$to" '{gsub(f, t)} 1' file

  • ,或者您可以使用perl和傳遞價值觀作爲環境變量

final=$(echo "$string" | perl_from="$from" perl_to="$to" perl -pe 's/$ENV{perl_from}/$ENV{perl_to}/') 
  • 或傳遞變量perl通過命令行ar guments
final=$(echo "$string" | perl -spe 's/$f/$t/' -- -f="$from" -t="$to") 
0

兩個選項:

1)拿不出在字符串中的字符(需要在內容檢查和可能焦炭預先過程不附帶一個字符可用)

# Quick and dirty sample using `'/_#@|!%=:;,-` arbitrary sequence 

Separator="$(printf "%sa%s%s" '/_#@|!%=:;,-' "${regexp}" "${replacement}" \ 
| sed -n ':cycle 
    s/\(.\)\(.*a.*\1.*\)\1/\1\2/g;t cycle 
    s/\(.\)\(.*a.*\)\1/\2/g;t cycle 
    s/^\(.\).*a.*/\1/p 
    ')" 
echo "Separator: [ ${Separator} ]" 
sed "s${Separator}${regexp}${Separator}${replacement}${Separator}flag" YourFile 

2)在字符串模式中轉義想要的字符(需要預處理來轉義字符)。

# Quick and dirty sample using # arbitrary with few escape security check 
regexpEsc="$(printf "%s" "${regexp}" | sed 's/#/\\#/g')" 
replacementEsc"$(printf "%s" "${replacement}" | sed 's/#/\\#/g')" 
sed 's#regexpEsc#replacementEsc#flags' YourFile 
0

man sed

\cregexpc 
      Match lines matching the regular expression regexp. The c may be any 
      character. 

當與路徑的工作,我經常使用#作爲分隔符:

sed s\#find/path#replace/path# 

沒有必要逃避/醜陋\/