【问题标题】:Sed replacing pattern starts with but not contains stringSed 替换模式以但不包含字符串开头
【发布时间】:2020-06-10 07:08:44
【问题描述】:

我有以下文本文件:file.text

Cygwin
value: c
Unix-keep
value: u
Linux
value: l
Unix-16
value: u
Solaris
value: s
Unix-replace-1
value: u
Unix-replace-2
value: u

我想根据前一个字符串替换所有行值:以 Unix- 开头但不包括包含字符串 keep

所以最终受影响的行应该是后面的行: 具有值 value: NEW_VERSION

的 Unix-replace-1 和 Unix-replace-2

预期输出:

Cygwin
value: c
Unix-keep
value: u
Linux
value: l
Unix-16
value: NEW_VERSION
Solaris
value: s
Unix-replace-1
value: NEW_VERSION
Unix-replace-2
value: NEW_VERSION

我尝试了以下 sed 脚本:

sed '/^Unix-/ {n;s/.*/value: NEW_VERSION/}' file.text

但这只能开始但不排除 -keep 子字符串。我不知道如何组合排除的。

有什么想法吗?

【问题讨论】:

  • 不要使用正则表达式解析 XML 或 HTML
  • 忽略xml格式,假设我们有文本文件,我们只需要替换Cygwin,Unix-keep,Solaris等后面的行。 Cygwin版本:c Unix-keep版本:u Unix-replace -1 版本:u 等
  • 你在一个专业的 QA 网站上,我们不鼓励人们用错误的工具做完全错误的事情

标签: unix awk sed


【解决方案1】:
$ awk -v new='NEW_VERSION' 'f{$0=$1 FS new} {f=(/^Unix-/ && !/keep/)} 1' file
Cygwin
value: c
Unix-keep
value: u
Linux
value: l
Unix-16
value: NEW_VERSION
Solaris
value: s
Unix-replace-1
value: NEW_VERSION
Unix-replace-2
value: NEW_VERSION

【讨论】:

  • 我可能有一些行以 Unix 作为起始字符但不包含 -replace- 子字符串。例如Unix-1、Unix-2 等
  • 当然,这只是软件,所以一切皆有可能。如果您在问题中提供的示例不能很好地代表您的真实数据,请修复您的示例以包括我发布的答案不起作用的情况以及您可能已经离开的其他任何情况(例如下雨天/边缘情况)出来。
  • 我修正了我的输入。逻辑是只识别以 Unix- 开头但不包含 keep 子字符串的行。 Unix-replace-1 , Unix-16, Unix----- (下一行没有 keep substring )应该只能替换
  • 谢谢。只是一个小观察:如果我想要更动态的替换线,解决方案是什么?例如值Unix:NEW_VERSION
【解决方案2】:

使用正确的 解析器(问题最初是由 OP 编辑​​之前的纯 XML):

已编辑为有效的 XML(缺少结束标记):

<project>
    <Cygwin>
        <version>c</version>
    </Cygwin>
    <Unix-keep>
        <version>u</version>
    </Unix-keep>
    <Linux>
        <version>l</version>
    </Linux>
    <Solaris>
        <version>s</version>
    </Solaris>
    <Unix-replace-1>
        <version>u</version>
    </Unix-replace-1>
    <AIX>
        <version>a</version>
    </AIX>
    <Unix-replace-2>
        <version>u</version>
    </Unix-replace-2>
</project>

命令:

xmlstarlet ed -u '//project/*
    [starts-with(name(), "Unix") and not(starts-with(name(), "Unix-keep"))]
    /version
' -v 'NEW_VERSION' file

要编辑文件就地,使用

xmlstarlet ed -L -u ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    • 2020-09-07
    • 2014-12-17
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    相关资源
    最近更新 更多