sed/awk替换包含任何可能可打印字符的复杂字符串



我需要替换一个可以包含任何可打印字符的复杂字符串。这是我一直无法使用sed替换的真实示例模式。

<!-- %cmd: for F in $(find ../[09]* -maxdepth 1 -type d -printf "%Pn" ) | grep -v "^$"; do echo "<li><a href="$F">$F</a></li>"; done -->

我什至在使用不可打印的SED定界符,以避免冲突,因为原始字符串应仅由可打印的字符组成:

DELIM=$(echo -en "01");

但行不通。我尝试了很多事情,我无法弄清楚我缺少什么。例如:

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 '%sn' "$pattern") <(printf '%s' "$container")

代码演示

您可以在SED的定界符中使用conrol字符:

pattern='foobar'
delim=$'1'
echo "before $pattern after" | sed "s${delim}${pattern}${delim}newtext${delim}"
before newtext after

更新:

由于您的图案包含各种特殊的元字符,因此最好使用awk抛弃REGEX(SED)并使用非regex替换:

pattern='<!-- %cmd: for F in $(find ../[09]* -maxdepth 1 -type d -printf "%Pn" ) | 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 "%sn" "$pattern") <(echo "before $pattern after")
before newtext after

代码演示

最新更新