使用 sed 替换更大模式中的两个模式

使用 sed 替换更大模式中的两个模式

使用 sed 如何在一行上替换更大模式中的两个模式?

给定一行文本,我想找到一个模式(我们称之为外部模式),然后在该外部模式内替换两个内部模式。

以下是输入文本的一行示例:

Z:\source\private\main\developer\foo\setenv.sh(25):     export 'FONTCONFIG_PATH'="$WINE_SHARED_SUPPORT/X11/etc/fonts"

在上面的例子中,外部模式/^.*\([[:digit:]]+\):/应该相等,Z:\source\private\main\developer\foo\setenv.sh(25):而两个内部模式是/^[A-Za-z]://\\/

提出我的问题的另一种方式是:

使用 sed 我知道如何使用命令执行模式替换s,但如何限制命令的范围s以使其仅对输入字符串的部分起作用(25):

我试图获得的最终结果是将文本行转换为如下形式:

/enlistments/source/private/main/developer/foo/setenv.sh(25):     export 'FONTCONFIG_PATH'="$WINE_SHARED_SUPPORT/X11/etc/fonts"

答案1

此命令将您的输入示例转换为输出示例:

sed 's|\\|/|g;s|^[^/]*|/enlistments|'

如果您的某些输入在部分之后的部分包含反斜杠/^.*([[:digit:]]+):/,那么您将必须分而治之以防止后面的反斜杠被替换。

sed 'h;s/^.*([[:digit:]]\+)://;x;s/^\(.*([[:digit:]]\+):\).*/\1/;s|\\|/|g;s|^[^/]*|/enlistments|;G;s/\n//'

说明(标有星号的步骤([*])适用于两个命令):

  • h- 复制该行以保留空间
  • s/^.*([[:digit:]]\+)://- 从模式空间中删除原始行的第一部分
  • x- 交换模式空间和保持空间
  • s/^\(.*([[:digit:]]\+):\).*/\1/- 保留副本中该行的第一部分(丢弃最后一部分)
  • s|\\|/|g-[ *]将所有反斜杠改为斜杠(在分治版本中,只有模式空间中的部分 - 即行的第一部分 - 受到影响)
  • s|^[^/]*|/enlistments|-[ *]将第一个斜线之前的内容更改为“/enlistments” - 如果需要,可以使其更具选择性
  • G- 将换行符和保留空间的内容附加到模式空间的末尾
  • s/\n//- 删除内部换行符

答案2

我认为有两个事实对你有用:

  1. 默认情况下,sed只会替换一行中第一次出现的字符串。因此,给定以下行:

    foo foo
    

    该命令sed s/foo/bar/将导致:

    bar foo
    
  2. 您可以将 sed 命令限制为与特定模式匹配的行。如果您只想对包含字符串“xyz”的行执行上述替换,则可以使用如下命令:

    sed '/xyz/ s/foo/bar/'
    

我认为这应该可以帮助你做你想做的事。

答案3

你可以尝试

sed -r 's/^[A-Z]:\\|\\/\//g' | sed 's/^/\/enlistments/'

现在,这当然要求 (25): 后面的部分没有反斜杠才能工作。但我怀疑,由于 unix 路径结构,这种情况永远不会发生。

答案4

这可能对你有用(GNU sed):

sed 's/([0-9]\+):/&\n/;h;s/\n.*//;y/\\/\//;s/[^/]*/\/enlistments/;G;s/\n.*\n//' file

相关内容