Awk one-liner to replace text of first matching regex occurence only -


i need awk command replace ss:width="252" in first xml tag in text ss:width="140" , leave rest of tags alone:

cat <<- eof > text     <ss:column ss:autofitwidth="1" ss:width="252"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="252"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="189"/>     <ss:column ss:autofitwidth="1" ss:width="189"/>     <ss:column ss:autofitwidth="1" ss:width="252"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="126"/>     <ss:column ss:autofitwidth="1" ss:width="252"/> eof  awk '{c=++count[$0]} c==1 {sub(/ss:width=\"[0-9]{1,4}\"/,"ss:width=\"140\"")} {print}' text > newf  cat newf 

instead, replaces expression in first instances of each of 3 unique matches (three total replacements, whereas want one.)

<ss:column ss:autofitwidth="1" ss:width="140"/> <ss:column ss:autofitwidth="1" ss:width="140"/> <ss:column ss:autofitwidth="1" ss:width="126"/> <ss:column ss:autofitwidth="1" ss:width="126"/> <ss:column ss:autofitwidth="1" ss:width="126"/> <ss:column ss:autofitwidth="1" ss:width="252"/> <ss:column ss:autofitwidth="1" ss:width="126"/> <ss:column ss:autofitwidth="1" ss:width="126"/> <ss:column ss:autofitwidth="1" ss:width="140"/> <ss:column ss:autofitwidth="1" ss:width="189"/> <ss:column ss:autofitwidth="1" ss:width="252"/> <ss:column ss:autofitwidth="1" ss:width="126"/> <ss:column ss:autofitwidth="1" ss:width="126"/> <ss:column ss:autofitwidth="1" ss:width="126"/> <ss:column ss:autofitwidth="1" ss:width="126"/> <ss:column ss:autofitwidth="1" ss:width="252"/> 

why behave way? how incrementer behaving in awk command? expected increment after first qualifying match of /ss:width=\".*\"/ seems it's not incrementing until unique matches found, ignoring subsequent non-unique matches only. right? tried force counter increment @ end of c == 1 block this:

awk '{c=++count[$0]} c==1 {sub(/ss:width=\".*\"/,"ss:width=\"140\"");c++} {print}' text > newf 

but same output. didn't have luck trying task in sed & i'd rather in awk anyway. i'm interested in understanding awk syntax.

edit: tested theory changing 1 of width attributes random number. replace 1 140. so, limiting first instance of matching expressions, not first matching expression itself.

edit: cody pointed out regex greedy. changed .* [0-9]{1,4} behavior same - still replaces first instance of every unique match. changed 1 of xml tags' width attributes 3rd unique number , updated output illustrate behavior i'm trying fix.

this aix/ksh.

awk 'found == 0 { found = sub(/ss:width=\"[0-9]{1,4}\"/,"ss:width=\"140\"")} //' text > newf 

you might able shorten bit.

your old approach keeping array of counters indexed line of input. that's why exhibiting behavior weren't expecting.

some of other answers assume lines match /ss:width/ regex and/or find width attribute @ end of line. it's true in case worthy of noting. decided not assume things in script above.


Comments

Popular posts from this blog

How to connect android app to App engine -

gcc - MinGW's ld cannot perform PE operations on non PE output file -

php - display validation error message next to the textbox in codeigniter -