使用sed将字符串替换为变量的内容,即使它是转义字符

时间:2010-02-13 15:08:10

标签: bash string sed

我正在使用 sed -e "s/\*DIVIDER\*/$DIVIDER/g"使用用户指定的字符串替换*DIVIDER*,该字符串存储在$DIVIDER中。问题是我希望他们能够将转义字符指定为分隔符,例如\ n或\ t。当我尝试这个时,我最后得到字母n或t,或者等等。

有没有人对如何做到这一点有任何想法?非常感谢!

编辑:这是脚本的内容,我必须遗漏一些东西。

curl --silent "$URL" > tweets.txt

if [[ `cat tweets.txt` == *\<error\>* ]]; then
    grep -E '(error>)' tweets.txt | \
    sed -e 's/<error>//' -e 's/<\/error>//' |
    sed -e 's/<[^>]*>//g' |

head $headarg | sed G | fmt

else
    echo $REPLACE | awk '{gsub(".", "\\\\&");print}'
    grep -E '(description>)' tweets.txt | \
    sed -n '2,$p' | \
    sed -e 's/<description>//' -e 's/<\/description>//' |
    sed -e 's/<[^>]*>//g' |
    sed -e 's/\&amp\;/\&/g' |
    sed -e 's/\&lt\;/\</g' |
    sed -e 's/\&gt\;/\>/g' |
    sed -e 's/\&quot\;/\"/g' |
    sed -e 's/\&....\;/\?/g' |
    sed -e 's/\&.....\;/\?/g' |
    sed -e 's/^  *//g' |
    sed -e :a -e '$!N;s/\n/\*DIVIDER\*/;ta' |   # Replace newlines with *divider*.
    sed -e "s/\*DIVIDER\*/${DIVIDER//\\/\\\\}/g" |          # Replace *DIVIDER* with the actual divider.

    head $headarg | sed G
fi

sed行的长列表正在替换XML源中的字符,最后两个是应该用指定字符替换换行符的那些。我知道用另一个换行替换换行似乎是多余的,但这是我能想出来让他们选择自己的分频器最简单的方法。分隔符替换适用于普通字符。

5 个答案:

答案 0 :(得分:7)

你可以使用bash来反转反斜杠:

sed -e "s/\*DIVIDER\*/${DIVIDER//\\/\\\\}/g"

语法为${name/pattern/string}。如果模式以/开头,则patternname的每个出现都会被string替换。否则只更换第一次出现。

答案 1 :(得分:1)

也许:

case "$DIVIDER" in
(*\\*) DIVIDER=$(echo "$DIVIDER" | sed 's/\\/\\\\/g');;
esac

我玩过这个剧本:

for DIVIDER in 'xx\n' 'xxx\\ddd' "xxx"
do
    echo "In:  <<$DIVIDER>>"
    case "$DIVIDER" in     (*\\*) DIVIDER=$(echo "$DIVIDER" | sed 's/\\/\\\\/g');;
    esac
    echo "Out: <<$DIVIDER>>"
done

在MacOS X上使用'ksh'或'bash'(但不是'sh')运行:

In:  <<xx\n>>
Out: <<xx\\n>>
In:  <<xxx\\ddd>>
Out: <<xxx\\\\ddd>>
In:  <<xxx>>
Out: <<xxx>>

答案 2 :(得分:1)

这似乎是一个简单的替代:

$ d='\n'
$ echo "a*DIVIDER*b" | sed "s/\*DIVIDER\*/$d/"
a
b

也许我不明白你想要完成什么。

那么也许这一步可以代替你的最后两个:

sed -n ":a;$ {s/\n/$DIVIDER/g;p;b};N;ba"

注意美元符号后面的空格。它阻止shell将“$ {s ...”解释为变量名。

正如 ghostdog74 建议的那样,您对sed的调用过多。您可以将许多管道字符更改为反斜杠(行继续),并从除第一个之外的所有部分删除“sed”(在任何地方留下“-e”)。 (另)

答案 3 :(得分:0)

您只需要转义转义字符。

\ n将匹配\ n

\将匹配\

\\将匹配\

答案 4 :(得分:0)

使用FreeBSD sed(例如在Mac OS X上)你必须预处理$ DIVIDER用户输入:

d='\n'
d='\t'
NL=$'\\\n'
TAB=$'\\\t'
d="${d/\\n/${NL}}"
d="${d/\\t/${TAB}}"
echo "a*DIVIDER*b" | sed -E -e "s/\*DIVIDER\*/${d}/"