Reputation: 79
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
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
Reputation: 185560
Using a proper xml 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