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

powershell Start-Process exit code -1073741502 when used with Credential from a windows service environment -

twig - Using Twigbridge in a Laravel 5.1 Package -

c# - LINQ join Entities from HashSet's, Join vs Dictionary vs HashSet performance -