使用 sed 替换字符串的多个变体

Replace multiple variations of a string using sed

我想使用 sed 替换字符串的变体。 字符串模式需要匹配一组可选的可重复字符 ("../") 和一个强制字符串 ("foo") 例如 ../富 ../../富 ../../../foo

我可以使用模式替换单个版本,例如 ../../../foo,这将使用 sed 产生:

sed - 's/\.\.\/\.\.\/\.\.\/foo/foo1/'

=> foo1 但我想扩展以匹配任何版本,所以我得到: ../foo => foo1 ../../foo => foo1 ../../../foo => foo1

如何使用 sed 实现此目的?

您可以使用

sed -E 's,(\.\./)+foo,foo1,' file > newfile

注意 -E 选项启用 POSIX ERE 语法,(...) 被解析为分组结构,+ 被解析为匹配一个或一个的量词量化子模式的出现次数更多。

如果您需要确保匹配出现在字符串的开头,请在开头添加^'s,^(\.\./)+foo,foo1,'。请注意,此处使用逗号作为正则表达式分隔符以避免转义 / 字符。

如果 foo 必须作为一个完整的单词匹配,并且它以单词字符结尾,请在 foo 之后添加 \> 结束单词边界结构。

参见 online demo:

s='../foo
../../foo
../../../foo'
sed -E 's,(\.\./)+foo,foo1,' <<< "$s"

输出:

foo1
foo1
foo1

使用 awk 你可以更简单地完成它,只需匹配模式,如果找到则打印新值。

s='../foo
../../foo
../../../foo'
echo "$s" | awk 'match([=10=],/(\.\.)+\/foo/){print "foo1"}'

解释: 简单的解释是:

  • 首先创建名为 s 的 shell 变量,其中包含 OP 在其中提到的 foo 值。
  • 然后通过 echo 命令打印它的值并将其作为标准输入发送到 awk 程序。
  • awk程序中,使用awkmatch函数匹配正则表达式(\.\.)+\/foo如果提到的正则表达式匹配则打印新值foo2案例.

正则表达式解释:

(\.\.)+\/foo:匹配出现 1 次或多次的 2 个文字点(一起)后跟 /foo 如果找到匹配则打印新值。

输出如下:

foo1
foo1
foo1