我需要替换一个可以包含任何可打印字符的复杂字符串。这是一个我无法使用sed
替换的真实示例模式。
<!-- %cmd: for F in $(find ../[09]* -maxdepth 1 -type d -printf "%P\n" ) | grep -v "^$"; do echo "<li><a href=\"$F\">$F</a></li>"; done -->
我甚至使用不可打印的sed分隔符以避免冲突,因为原始字符串应仅由可打印字符组成:
DELIM=$(echo -en "\001");
但它不起作用。我尝试了很多东西,但我无法弄清楚我错过了什么。 E.g:
echo "BEFORE $PATTERN AFTER" | sed -e "s${DELIM}${PATTERN}${DELIM}NEWTEXT${DELIM}"
UPDATE-1:
提供的解决方案应该打印容器文本的所有行,同时用新的替换匹配的字符串。
pattern='<!-- %cmd: for F in $(find ../[0-9]* -maxdepth 0 -type d | sed "s/^\.\.\///"); do echo "<li><a href=\"$F\">$F</a></li>"; done -->'
container='
<h2>Title</h2>
<ul>
<!-- %cmd: for F in $(find ../[0-9]* -maxdepth 0 -type d | sed "s/^\.\.\///"); do echo "<li><a href=\"$F\">$F</a></li>"; done -->
</ul>
'
UPDATE-2:
经过几次迭代,这是@anubhava建立的工作,最终和接受的答案:
awk -v repl="newtext" 'FNR==NR {
a = a $0; next
} n = index($0, a) {
$0 = substr($0, 1, n-1) repl substr($0, n+length(a))
} 1' < (printf '%s\n' "$pattern") <(printf '%s' "$container")
答案 0 :(得分:2)
您可以在sed的分隔符中使用conrol字符,如下所示:
pattern='foobar'
delim=$'\01'
echo "before $pattern after" | sed "s${delim}${pattern}${delim}newtext${delim}"
before newtext after
<强>更新强>
由于您的模式包含各种特殊元字符,因此最好使用awk
抛弃正则表达式(sed)并使用非正则表达式替换:
pattern='<!-- %cmd: for F in $(find ../[09]* -maxdepth 1 -type d -printf "%P\n" ) | grep -v "^$"; do echo "<li><a href=\"$F\">$F</a></li>"; done -->'
awk -v repl="newtext" 'FNR==NR {
a = a $0; next
}
n = index($0, a) {
$0 = substr($0, 1, n-1) repl substr($0, n+length(a))
} 1' <(printf "%s\n" "$pattern") <(echo "before $pattern after")
before newtext after