spyDeveloper
spyDeveloper

Reputation: 79

Sed replacing pattern starts with but not contains string

I have the following text file: 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

I want to replace all lines values based on previous string : starting with Unix- but excluding containing string keep

So in the end affected lines sould be the ones after: Unix-replace-1 and Unix-replace-2 with value value: NEW_VERSION

Expected output:

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

I tried following sed script:

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

but this can only get starting but not excluding -keep substrings. I am not sure how to combine the excluded ones.

Any ideas?

Upvotes: 0

Views: 403

Answers (2)

Ed Morton
Ed Morton

Reputation: 204259

$ 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

Upvotes: 2

Gilles Quénot
Gilles Quénot

Reputation: 185560

Using a proper parser (the question was originally plain XML before edited by OP):

The XML edited to be valid (closing tags missing) :

<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>

The command:

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

To edit the file in place, use

xmlstarlet ed -L -u ...

Upvotes: 1

Related Questions