Replace lines after a given number of matches on separate lines with AWK
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
add a comment |
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
1
Settingmatches=4doesn't do what's needed: you need to start withmatches=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 addmatches > 3 && matches < 9to 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
add a comment |
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
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
linux bash shell-script sed awk
edited Dec 3 at 23:53
asked Dec 3 at 23:16
AndreasKralj
124
124
1
Settingmatches=4doesn't do what's needed: you need to start withmatches=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 addmatches > 3 && matches < 9to 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
add a comment |
1
Settingmatches=4doesn't do what's needed: you need to start withmatches=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 addmatches > 3 && matches < 9to 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
add a comment |
1 Answer
1
active
oldest
votes
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.
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
1
Setting
matches=4doesn't do what's needed: you need to start withmatches=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 < 9to 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