如何使用‘sed’命令将匹配的模式保存到变量中?

如何使用‘sed’命令将匹配的模式保存到变量中?

我试图首先使用sed命令来找到一种模式file.txt字符1字符2 然后用字符串替换它。像下面的echo模式示例一样:

echo "This X is test Y. But X is not test Y." | sed 's/X[^Y]*Y/REPLACE/'

另外,我需要将匹配的模式(如is test{<--spaces around is important} )保存在变量中。

答案1

这里是 sed 的一次调用,将修改后的行写入 stdout,同时将删除的文本保存在 shell 变量中var

$ var=$(echo "This X is test Y. But X is not test Y." | sed -nr 'h;s/[^X]*X([^Y]*)Y.*/\1/;p;x;s/X[^Y]*Y/REPLACE/;w /dev/stderr') 2>&1
This REPLACE. But X is not test Y.

的值为var

$ echo "==$var=="
== is test ==

解释:

  • h

    此命令将当前模式复制到保持空间。

  • s/[^X]*X([^Y]*)Y.*/\1/;p

    X这将从模式空间中删除所有内容,除了第一个和之间的文本Y(包括任何空格)。然后将其打印到 stdout。这是由 shell 捕获并分配给 的输出var

  • x

    这会将保留空间复制回模式空间。完成后,模式空间包含原始输入行的副本。

  • s/X[^Y]*Y/REPLACE/; w /dev/stderr

    进行替换并将结果写入stderr

  • 2>&1

    在 shell 将 stdout 捕获到 之后var,这将指示 shell 将 stderr(包含 REPLACE 行)复制到 stdout。

除了处理变量var

变量var包含前导空格和尾随空格。如果 shell 随后要var进行分词,这些空格将被删除。为了防止这种情况,在var引用时,请将其放在双引号内,如上例所示。

答案2

您必须使用第二个 sed 命令来完成此操作:

var=$(echo "This X is test Y. But X is not test Y." | \
tee >(sed 's/X[^Y]*Y/REPLACE/' >/dev/stderr) | \
sed -r 's/[^X]*X([^Y]*)Y.*/\1/')

说明:

  • 您必须使用tee来分割流。它既包含字符串,stdoutstderr包含字符串。
  • tee需要一个文件作为参数。我们给出tee一个管道,用于sed监听并替换字符串。
  • sed将字符串打印到stderr:您在终端中看到的输出。
  • 第二条sed命令监听stdout并提取所需的字符串,现在将其保存到变量中$var(的内容stdout)。

使用它来检查:

$ echo ">$var<"
> is test <

相关内容