Replace lines after a given number of matches on separate lines with AWK












0














Currently I'm using AWK to find and replace a portion of a string after the first three occurrences of a pattern. The string is formatted like this: func(tempID="39849235",count='12');, and there are many of these strings in the file as shown below:



func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');


Using this link, I was able to find a method of using AWK to find and replace the first three instances of the string. I changed it to what I needed it to do, and a snippet of my script is below:



id=12349876
awk -v id="$id" 'BEGIN {matches=0}
matches < 3 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id"""); matches++ }
{ print $0 }' filName.py >filName.py.changed


The goal of the above code is to match on any line containing tempID and replace the number that is assigned to tempID with a value held in a variable named $id. The find and replace works well, but now I want to replace instances 4-9 with a different number. I tried the following method, but it still only replaced the first 5 instances of tempID:



id2=39843237
awk -v id2="$id2" 'BEGIN {matches=4}
matches < 9 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id2"""); matches++ }
{ print $0 }' filName.py >filName.py.changed


Is there another way to implement this so that that range of values is replaced? It doesn't have to be with AWK, it can be with sed or any other Linux utility. In addition, the solution doesn't necessarily have to end at a certain point and is allowed to replace all instances after the third line, but if there's a solution that can do this, that would be a plus.










share|improve this question




















  • 1




    Setting matches=4 doesn't do what's needed: you need to start with matches=0, as before, then check for its value being 3 or more, as well as less than 9.
    – AFH
    Dec 3 at 23:31










  • Good catch on that bug @KamilMaciorowski, edited.
    – AndreasKralj
    Dec 3 at 23:54












  • @AFH Gotcha, thanks. I think I understand where you're coming from. Are you suggesting I simply need to add matches > 3 && matches < 9 to my code?
    – AndreasKralj
    Dec 4 at 0:15












  • Yes, but @KamilMaciorowski has covered all the issues in his answer.
    – AFH
    Dec 4 at 14:11
















0














Currently I'm using AWK to find and replace a portion of a string after the first three occurrences of a pattern. The string is formatted like this: func(tempID="39849235",count='12');, and there are many of these strings in the file as shown below:



func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');


Using this link, I was able to find a method of using AWK to find and replace the first three instances of the string. I changed it to what I needed it to do, and a snippet of my script is below:



id=12349876
awk -v id="$id" 'BEGIN {matches=0}
matches < 3 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id"""); matches++ }
{ print $0 }' filName.py >filName.py.changed


The goal of the above code is to match on any line containing tempID and replace the number that is assigned to tempID with a value held in a variable named $id. The find and replace works well, but now I want to replace instances 4-9 with a different number. I tried the following method, but it still only replaced the first 5 instances of tempID:



id2=39843237
awk -v id2="$id2" 'BEGIN {matches=4}
matches < 9 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id2"""); matches++ }
{ print $0 }' filName.py >filName.py.changed


Is there another way to implement this so that that range of values is replaced? It doesn't have to be with AWK, it can be with sed or any other Linux utility. In addition, the solution doesn't necessarily have to end at a certain point and is allowed to replace all instances after the third line, but if there's a solution that can do this, that would be a plus.










share|improve this question




















  • 1




    Setting matches=4 doesn't do what's needed: you need to start with matches=0, as before, then check for its value being 3 or more, as well as less than 9.
    – AFH
    Dec 3 at 23:31










  • Good catch on that bug @KamilMaciorowski, edited.
    – AndreasKralj
    Dec 3 at 23:54












  • @AFH Gotcha, thanks. I think I understand where you're coming from. Are you suggesting I simply need to add matches > 3 && matches < 9 to my code?
    – AndreasKralj
    Dec 4 at 0:15












  • Yes, but @KamilMaciorowski has covered all the issues in his answer.
    – AFH
    Dec 4 at 14:11














0












0








0







Currently I'm using AWK to find and replace a portion of a string after the first three occurrences of a pattern. The string is formatted like this: func(tempID="39849235",count='12');, and there are many of these strings in the file as shown below:



func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');


Using this link, I was able to find a method of using AWK to find and replace the first three instances of the string. I changed it to what I needed it to do, and a snippet of my script is below:



id=12349876
awk -v id="$id" 'BEGIN {matches=0}
matches < 3 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id"""); matches++ }
{ print $0 }' filName.py >filName.py.changed


The goal of the above code is to match on any line containing tempID and replace the number that is assigned to tempID with a value held in a variable named $id. The find and replace works well, but now I want to replace instances 4-9 with a different number. I tried the following method, but it still only replaced the first 5 instances of tempID:



id2=39843237
awk -v id2="$id2" 'BEGIN {matches=4}
matches < 9 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id2"""); matches++ }
{ print $0 }' filName.py >filName.py.changed


Is there another way to implement this so that that range of values is replaced? It doesn't have to be with AWK, it can be with sed or any other Linux utility. In addition, the solution doesn't necessarily have to end at a certain point and is allowed to replace all instances after the third line, but if there's a solution that can do this, that would be a plus.










share|improve this question















Currently I'm using AWK to find and replace a portion of a string after the first three occurrences of a pattern. The string is formatted like this: func(tempID="39849235",count='12');, and there are many of these strings in the file as shown below:



func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');
func(tempID="39849235",count='12');


Using this link, I was able to find a method of using AWK to find and replace the first three instances of the string. I changed it to what I needed it to do, and a snippet of my script is below:



id=12349876
awk -v id="$id" 'BEGIN {matches=0}
matches < 3 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id"""); matches++ }
{ print $0 }' filName.py >filName.py.changed


The goal of the above code is to match on any line containing tempID and replace the number that is assigned to tempID with a value held in a variable named $id. The find and replace works well, but now I want to replace instances 4-9 with a different number. I tried the following method, but it still only replaced the first 5 instances of tempID:



id2=39843237
awk -v id2="$id2" 'BEGIN {matches=4}
matches < 9 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id2"""); matches++ }
{ print $0 }' filName.py >filName.py.changed


Is there another way to implement this so that that range of values is replaced? It doesn't have to be with AWK, it can be with sed or any other Linux utility. In addition, the solution doesn't necessarily have to end at a certain point and is allowed to replace all instances after the third line, but if there's a solution that can do this, that would be a plus.







linux bash shell-script sed awk






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 3 at 23:53

























asked Dec 3 at 23:16









AndreasKralj

124




124








  • 1




    Setting matches=4 doesn't do what's needed: you need to start with matches=0, as before, then check for its value being 3 or more, as well as less than 9.
    – AFH
    Dec 3 at 23:31










  • Good catch on that bug @KamilMaciorowski, edited.
    – AndreasKralj
    Dec 3 at 23:54












  • @AFH Gotcha, thanks. I think I understand where you're coming from. Are you suggesting I simply need to add matches > 3 && matches < 9 to my code?
    – AndreasKralj
    Dec 4 at 0:15












  • Yes, but @KamilMaciorowski has covered all the issues in his answer.
    – AFH
    Dec 4 at 14:11














  • 1




    Setting matches=4 doesn't do what's needed: you need to start with matches=0, as before, then check for its value being 3 or more, as well as less than 9.
    – AFH
    Dec 3 at 23:31










  • Good catch on that bug @KamilMaciorowski, edited.
    – AndreasKralj
    Dec 3 at 23:54












  • @AFH Gotcha, thanks. I think I understand where you're coming from. Are you suggesting I simply need to add matches > 3 && matches < 9 to my code?
    – AndreasKralj
    Dec 4 at 0:15












  • Yes, but @KamilMaciorowski has covered all the issues in his answer.
    – AFH
    Dec 4 at 14:11








1




1




Setting matches=4 doesn't do what's needed: you need to start with matches=0, as before, then check for its value being 3 or more, as well as less than 9.
– AFH
Dec 3 at 23:31




Setting matches=4 doesn't do what's needed: you need to start with matches=0, as before, then check for its value being 3 or more, as well as less than 9.
– AFH
Dec 3 at 23:31












Good catch on that bug @KamilMaciorowski, edited.
– AndreasKralj
Dec 3 at 23:54






Good catch on that bug @KamilMaciorowski, edited.
– AndreasKralj
Dec 3 at 23:54














@AFH Gotcha, thanks. I think I understand where you're coming from. Are you suggesting I simply need to add matches > 3 && matches < 9 to my code?
– AndreasKralj
Dec 4 at 0:15






@AFH Gotcha, thanks. I think I understand where you're coming from. Are you suggesting I simply need to add matches > 3 && matches < 9 to my code?
– AndreasKralj
Dec 4 at 0:15














Yes, but @KamilMaciorowski has covered all the issues in his answer.
– AFH
Dec 4 at 14:11




Yes, but @KamilMaciorowski has covered all the issues in his answer.
– AFH
Dec 4 at 14:11










1 Answer
1






active

oldest

votes


















0














Your matches=4 and matches < 9 mean "assume there were 4 matches already, act until there are 9 in total". That's why the first 5 instances are replaced. You need to start form 0 as before, then include the lower limit into the logic:



id2=39843237
awk -v id2="$id2" 'BEGIN {matches=0}
matches >=3 && matches < 9 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id2""") }
/.*tempID.*/ { matches++ }
{ print $0 }' filName.py >filName.py.changed


Note you need to do the replacement according to the value of matches but you need to increase this value every time a match occurs. Your original code replaced text and increased the value in one block. When there was no replacement due to matches being too high, the value was not increased further, but it didn't matter anymore. Now you can't get away with this simple approach. When there is no replacement due to matches being too low, you still need to increase the value if there's a matching string found.



Hence the two {} blocks with separate conditions.






share|improve this answer





















  • This was exactly what I was looking for and works great, thank you! I asked pretty much the same question on stackoverflow here, please feel free to submit this answer on that one as well and I'll accept it.
    – AndreasKralj
    Dec 4 at 1:24












  • @AndreasKralj Well… Is cross-posting a question on multiple Stack Exchange sites permitted if the question is on-topic for each site?
    – Kamil Maciorowski
    Dec 4 at 5:29










  • Very well. I'll close the other answer since this one took care of what I wanted.
    – AndreasKralj
    Dec 4 at 23:35











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "3"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1380543%2freplace-lines-after-a-given-number-of-matches-on-separate-lines-with-awk%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














Your matches=4 and matches < 9 mean "assume there were 4 matches already, act until there are 9 in total". That's why the first 5 instances are replaced. You need to start form 0 as before, then include the lower limit into the logic:



id2=39843237
awk -v id2="$id2" 'BEGIN {matches=0}
matches >=3 && matches < 9 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id2""") }
/.*tempID.*/ { matches++ }
{ print $0 }' filName.py >filName.py.changed


Note you need to do the replacement according to the value of matches but you need to increase this value every time a match occurs. Your original code replaced text and increased the value in one block. When there was no replacement due to matches being too high, the value was not increased further, but it didn't matter anymore. Now you can't get away with this simple approach. When there is no replacement due to matches being too low, you still need to increase the value if there's a matching string found.



Hence the two {} blocks with separate conditions.






share|improve this answer





















  • This was exactly what I was looking for and works great, thank you! I asked pretty much the same question on stackoverflow here, please feel free to submit this answer on that one as well and I'll accept it.
    – AndreasKralj
    Dec 4 at 1:24












  • @AndreasKralj Well… Is cross-posting a question on multiple Stack Exchange sites permitted if the question is on-topic for each site?
    – Kamil Maciorowski
    Dec 4 at 5:29










  • Very well. I'll close the other answer since this one took care of what I wanted.
    – AndreasKralj
    Dec 4 at 23:35
















0














Your matches=4 and matches < 9 mean "assume there were 4 matches already, act until there are 9 in total". That's why the first 5 instances are replaced. You need to start form 0 as before, then include the lower limit into the logic:



id2=39843237
awk -v id2="$id2" 'BEGIN {matches=0}
matches >=3 && matches < 9 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id2""") }
/.*tempID.*/ { matches++ }
{ print $0 }' filName.py >filName.py.changed


Note you need to do the replacement according to the value of matches but you need to increase this value every time a match occurs. Your original code replaced text and increased the value in one block. When there was no replacement due to matches being too high, the value was not increased further, but it didn't matter anymore. Now you can't get away with this simple approach. When there is no replacement due to matches being too low, you still need to increase the value if there's a matching string found.



Hence the two {} blocks with separate conditions.






share|improve this answer





















  • This was exactly what I was looking for and works great, thank you! I asked pretty much the same question on stackoverflow here, please feel free to submit this answer on that one as well and I'll accept it.
    – AndreasKralj
    Dec 4 at 1:24












  • @AndreasKralj Well… Is cross-posting a question on multiple Stack Exchange sites permitted if the question is on-topic for each site?
    – Kamil Maciorowski
    Dec 4 at 5:29










  • Very well. I'll close the other answer since this one took care of what I wanted.
    – AndreasKralj
    Dec 4 at 23:35














0












0








0






Your matches=4 and matches < 9 mean "assume there were 4 matches already, act until there are 9 in total". That's why the first 5 instances are replaced. You need to start form 0 as before, then include the lower limit into the logic:



id2=39843237
awk -v id2="$id2" 'BEGIN {matches=0}
matches >=3 && matches < 9 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id2""") }
/.*tempID.*/ { matches++ }
{ print $0 }' filName.py >filName.py.changed


Note you need to do the replacement according to the value of matches but you need to increase this value every time a match occurs. Your original code replaced text and increased the value in one block. When there was no replacement due to matches being too high, the value was not increased further, but it didn't matter anymore. Now you can't get away with this simple approach. When there is no replacement due to matches being too low, you still need to increase the value if there's a matching string found.



Hence the two {} blocks with separate conditions.






share|improve this answer












Your matches=4 and matches < 9 mean "assume there were 4 matches already, act until there are 9 in total". That's why the first 5 instances are replaced. You need to start form 0 as before, then include the lower limit into the logic:



id2=39843237
awk -v id2="$id2" 'BEGIN {matches=0}
matches >=3 && matches < 9 && /.*tempID.*/ { sub(/tempID=.[0-9]+./,"tempID=""id2""") }
/.*tempID.*/ { matches++ }
{ print $0 }' filName.py >filName.py.changed


Note you need to do the replacement according to the value of matches but you need to increase this value every time a match occurs. Your original code replaced text and increased the value in one block. When there was no replacement due to matches being too high, the value was not increased further, but it didn't matter anymore. Now you can't get away with this simple approach. When there is no replacement due to matches being too low, you still need to increase the value if there's a matching string found.



Hence the two {} blocks with separate conditions.







share|improve this answer












share|improve this answer



share|improve this answer










answered Dec 4 at 0:17









Kamil Maciorowski

23.9k155175




23.9k155175












  • This was exactly what I was looking for and works great, thank you! I asked pretty much the same question on stackoverflow here, please feel free to submit this answer on that one as well and I'll accept it.
    – AndreasKralj
    Dec 4 at 1:24












  • @AndreasKralj Well… Is cross-posting a question on multiple Stack Exchange sites permitted if the question is on-topic for each site?
    – Kamil Maciorowski
    Dec 4 at 5:29










  • Very well. I'll close the other answer since this one took care of what I wanted.
    – AndreasKralj
    Dec 4 at 23:35


















  • This was exactly what I was looking for and works great, thank you! I asked pretty much the same question on stackoverflow here, please feel free to submit this answer on that one as well and I'll accept it.
    – AndreasKralj
    Dec 4 at 1:24












  • @AndreasKralj Well… Is cross-posting a question on multiple Stack Exchange sites permitted if the question is on-topic for each site?
    – Kamil Maciorowski
    Dec 4 at 5:29










  • Very well. I'll close the other answer since this one took care of what I wanted.
    – AndreasKralj
    Dec 4 at 23:35
















This was exactly what I was looking for and works great, thank you! I asked pretty much the same question on stackoverflow here, please feel free to submit this answer on that one as well and I'll accept it.
– AndreasKralj
Dec 4 at 1:24






This was exactly what I was looking for and works great, thank you! I asked pretty much the same question on stackoverflow here, please feel free to submit this answer on that one as well and I'll accept it.
– AndreasKralj
Dec 4 at 1:24














@AndreasKralj Well… Is cross-posting a question on multiple Stack Exchange sites permitted if the question is on-topic for each site?
– Kamil Maciorowski
Dec 4 at 5:29




@AndreasKralj Well… Is cross-posting a question on multiple Stack Exchange sites permitted if the question is on-topic for each site?
– Kamil Maciorowski
Dec 4 at 5:29












Very well. I'll close the other answer since this one took care of what I wanted.
– AndreasKralj
Dec 4 at 23:35




Very well. I'll close the other answer since this one took care of what I wanted.
– AndreasKralj
Dec 4 at 23:35


















draft saved

draft discarded




















































Thanks for contributing an answer to Super User!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1380543%2freplace-lines-after-a-given-number-of-matches-on-separate-lines-with-awk%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Terni

A new problem with tex4ht and tikz

Sun Ra