I'm trying to remove the first match only of 2Z694 from an xml file and replace with a blank
File Example:
</Phoenix_Response_Data>
<Bundle_Name_Primary>2Z694</Bundle_Name_Primary>
<Bundle_Name>2Z694</Bundle_Name>
</Phoenix_Response_Data>
tried using:
sed -e 's/'2Z694'/''/1'
but this blanks out all instances of 2Z694.
Does it have to be sed?
perl -0pe 's/2Z694//' file.xml
RudiC
August 28, 2014, 4:38am
3
sed '/2Z694/,$ {1,1 s/2Z694/ /}' file
</Phoenix_Response_Data>
<Bundle_Name_Primary> </Bundle_Name_Primary>
<Bundle_Name>2Z694</Bundle_Name>
</Phoenix_Response_Data>
Thanks for the reply Rudi but your suggestion returns an error
sed: 1: "/2Z694-00609/,$ {1,1 s/ ...": bad flag in substitute command: '}'
Below is the file and I'm trying to strip out the first and only match of 2Z694-00609
<?xml version="1.0" encoding="UTF-8"?><SI_Response><SI_Response_Header><Command_Name>Comm.Get.BundleList</Command_Name><Supported>SUPPORTED</Supported><Responses_Sent>1</Responses_Sent><Responses_Expected>1</Responses_Expected><App_Name>phoenixd-7700</App_Name><Sequence_Number>1</Sequence_Number><Error_Code>0</Error_Code><Error_Msg></Error_Msg></SI_Response_Header><SI_Response_Data>
<Phoenix_Response>
<Phoenix_Response_Header version="1.0"></Phoenix_Response_Header>
<Phoenix_Response_Data>
<Bundle_Name>2Z694-00609</Bundle_Name>
<Bundle_Name_Primary>2Z694-00609</Bundle_Name_Primary>
</Phoenix_Response_Data>
</Phoenix_Response>
</SI_Response_Data></SI_Response>
This is what I have tried ...
BundleName=`cat /Phoenix/Configuration/bundlelist.txt | grep -m 1 "2Z694" | awk -F "[>,<]" '{print$3}'`
echo Bundlelist found is $BundleName
cp -f /Phoenix/Configuration/bundlelist.txt /Phoenix/bundlelist1.txt
sed '/'2Z694-00609'/,$ {1,1 s/'$2Z694-00609'/ /}' /Phoenix/bundlelist1.txt > /Phoenix/Configuration/bundlelist.txt
Any other ideas, thanks again ...
With awk:
awk '!p{p=sub("2Z694-00609",x)}1' file
2 Likes
RudiC
August 28, 2014, 7:50am
6
Must be a different sed
version:
sed '/2Z694-00609/,$ {1,1 s/2Z694-00609/ /}' file
<?xml version="1.0" encoding="UTF-8"?><SI_Response><SI_Response_Header><Command_Name>Comm.Get.BundleList</Command_Name><Supported>SUPPORTED</Supported><Responses_Sent>1</Responses_Sent><Responses_Expected>1</Responses_Expected><App_Name>phoenixd-7700</App_Name><Sequence_Number>1</Sequence_Number><Error_Code>0</Error_Code><Error_Msg></Error_Msg></SI_Response_Header><SI_Response_Data>
<Phoenix_Response>
<Phoenix_Response_Header version="1.0"></Phoenix_Response_Header>
<Phoenix_Response_Data>
<Bundle_Name> </Bundle_Name>
<Bundle_Name_Primary>2Z694-00609</Bundle_Name_Primary>
</Phoenix_Response_Data>
</Phoenix_Response>
</SI_Response_Data></SI_Response>
sed --version
sed (GNU sed) 4.2.2
Thanks Franklin, awk works as expected. Rudi I'm running off Mac OS X 10.8 so see version different. Thanks again
Simple, only delete in the range including the first pattern:
sed '
1,/pattern/{
s/pattern/new/
}
' in_file >out_file
It is even easier than that: just quit sed after the first match:
sed '/<pattern>/ {;s/<pattern>/<subst>/;q;}' /your/input/file
I hope this helps.
bakunin
No, that loses the tail of the file. You cannot quit.
You are right. If you need the tail, you cannot. Somehow i misread the problem statement yesterday and was under the impression that the tail wasn't important. My bad.
bakunin
dgpickett:
Simple, only delete in the range including the first pattern:
sed '
1,/pattern/{
s/pattern/new/
}
' in_file >out_file
As long as the first occurrence of the pattern isn't on the first line, otherwise it will delete two..
GNU sed can use this:
gsed '0,/pattern/{s/pattern//;}' file
or even:
gsed '0,/pattern/{s///}' file
---
Is the 1,1
an undocumented feature of GNU sed ?
Why would the first 1 become true?
In regular sed it does not work:
sed '/2Z694/,$ { 1,1 s/2Z694//;}' infile3104
</Phoenix_Response_Data>
<Bundle_Name_Primary>2Z694</Bundle_Name_Primary>
<Bundle_Name>2Z694</Bundle_Name>
</Phoenix_Response_Data>
It only works if the first line number is the actual line number
$ sed '/2Z694/,$ { 2,1 s/2Z694//;}' file
</Phoenix_Response_Data>
<Bundle_Name_Primary></Bundle_Name_Primary>
<Bundle_Name>2Z694</Bundle_Name>
</Phoenix_Response_Data>
But that would of course not be useful...
RudiC
August 29, 2014, 11:42am
13
I ran into this a few times before, and I was surprised as well. Mayhap it's only GNU sed that does this. It seems starting over counting lines in the {...}block, but the line no. printed by "=" is the real file's one. And, it needs the range "1,1". Just the "1" address doesn't work.
I don't think it starts over counting. It looks more like a bug to me:
$ gsed '/2Z694/,$ { 1,1 s/2Z694//;}' file
</Phoenix_Response_Data>
<Bundle_Name_Primary></Bundle_Name_Primary>
<Bundle_Name>2Z694</Bundle_Name>
</Phoenix_Response_Data>
$ gsed '/2Z694/,$ { 2,1 s/2Z694//;}' file
</Phoenix_Response_Data>
<Bundle_Name_Primary></Bundle_Name_Primary>
<Bundle_Name>2Z694</Bundle_Name>
</Phoenix_Response_Data>
$ gsed '/2Z694/,$ { 3,1 s/2Z694//;}' file
</Phoenix_Response_Data>
<Bundle_Name_Primary>2Z694</Bundle_Name_Primary>
<Bundle_Name></Bundle_Name>
</Phoenix_Response_Data>
RudiC
August 29, 2014, 1:24pm
15
Yes, strange enough. It doesn't care what range it is, as long as the begin is below the line number. Doesn't look like sth you should rely upon.
Regular sed can avoid first line problems and double maching test but needs a complex tail copier:
sed '
s/pattern/new/
t loop
b
:loop
$b
N
P
s/.*\n//
b loop
' in_file >out_file
Once the first s fires, flow transfers into loop to copy the tail out. It's a shame sed does not have a variation on D to delete the first line or all but the last line and leave the buffer and flow intact.