我想查找并替换一个模式,但它也环绕到下一行,我需要找到某种方法来处理这个问题
看起来像这样的东西:
....tr("Changes to output mappings will be deleted. "
"There is no undo available. Do you want to continue?"));
变成类似的东西
...."Changes to output mappings will be deleted. "
"There is no undo available. Do you want to continue?");
(...是以前的代码)
到目前为止,我的代码如下(适用于单行,但不适用于换行的文本/代码):
sed -i 's/tr(\([^)]*\))/\1/I' $file_t
我该怎么办呢?
答案1
tr(
对于命令始终分布在两行上的情况,请尝试:
$ sed '/tr(/N; s/tr(\([^)]*\))/\1/I' "$file_t"
...."Changes to output mappings will be deleted. "
"There is no undo available. Do you want to continue?");
这里唯一的变化是添加了/tr(/N
.对于任何匹配 的行tr(
,它会读入下一行并将其添加到模式空间 ( N
)。
要就地更改文件,请使用-i
:
sed -i.bak '/tr(/N; s/tr(\([^)]*\))/\1/I' "$file_t"
更强大的版本
如果tr(...)
命令可能出现在一行、两行或多于两行,我们需要稍微改变一下逻辑:
sed '/tr(/{ :a; s/tr(\([^)]*\))/\1/I; t; N; ba}' filename
这会查找包含 的行tr(
。对于任何此类行,{...}
都会执行大括号 , 中的命令。对于这些行,首先仅在该行上尝试替换。如果发生替换,则该t
命令告诉 sed 我们已经完成了这一行。如果没有发生,意味着没有结束)
,则在 ( ) 中读取下一行N
,并且 sed 分支回标签a
( ba
) 并再次尝试替换。重复此操作,直到读入足够的行以找到)
.
例如,这是一个tr(...)
分布在一行、两行和三行的文件:
$ cat filename
tr("abc");
....tr("Changes to output mappings will be deleted. "
"There is no undo available. Do you want to continue?"));
tr("one
two
three");
这是输出:
$ sed '/tr(/{ :a; s/tr(\([^)]*\))/\1/I; t; N; ba}' filename
"abc";
...."Changes to output mappings will be deleted. "
"There is no undo available. Do you want to continue?");
"one
two
three";
tr(...)
和之间的区别Ptr(...)
为了确保我们只替换tr
而不是替换Ptr
或Str
,我们需要确保tr
从单词边界开始。对于 GNU sed (Linux),字边界表示为\b
:
sed '/\btr(/{ :a; s/\btr(\([^)]*\))/\1/I; t; N; ba}' filename
使用 BSD (OSX) sed,下列可能有效:
sed '/[[:<:]]tr(/{ :a; s/[[:<:]]tr(\([^)]*\))/\1/I; t; N; ba}' filename