简体   繁体   English

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

[英]Sed/Awk replace complex string containing any possible printable character

I need to replace a complex string that can contain any printable characters. 我需要替换一个可以包含任何可打印字符的复杂字符串。 This is a real example pattern that I've been unable to replace using sed . 这是一个真实的示例模式,我无法使用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 -->

I'm even using a non-printable sed delimiter in order to avoid conflicts since the original string should be composed only of printable characters: 为了避免冲突,我什至使用了不可打印的sed分隔符,因为原始字符串应仅由可打印的字符组成:

DELIM=$(echo -en "\001");

But it doesn't work. 但这是行不通的。 I've tried many things, and I can't figure out what I'm missing. 我已经尝试了很多事情,但我无法弄清我所缺少的。 Eg: 例如:

echo "BEFORE $PATTERN AFTER" | sed -e "s${DELIM}${PATTERN}${DELIM}NEWTEXT${DELIM}"

UPDATE-1: UPDATE-1:

The provided solution should print all the lines of the container text, while replacing the matching string with a new one. 提供的解决方案应打印容器文本的所有行,同时用新的替换匹配的字符串。

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: UPDATE-2:

After a couple of iterations, this is the working, final and accepted answer built by @anubhava: 经过几次迭代,这是@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")

Code demo 代码演示

You can use conrol characters in sed's delimiter like this: 您可以在sed的分隔符中使用控制字符,如下所示:

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

before newtext after

Update: 更新:

As your pattern contain all sorts of special meta characters, it is better to ditch regex (sed) and use non-regex replacement using awk : 由于您的模式包含各种特殊的元字符,因此最好抛弃正则表达式(sed)并使用awk使用非正则表达式替换:

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

Code Demo 代码演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM