Using sed to edit any one of the occurrence of a matching pattern
A line starting with Fred Flintstone shall be appended with some string. Look for specified occurrence of Fred Flintstone and append it.
How do I use this command for anyone of the occurrences of such a pattern? I tried
sed '/Fred Flintstone/ s/$/ someString/2' filename
Apparently the above one isn't working. It works well for all occurrences, but not a specific occurrence. (Say I want to replace first or second or third [any one of them])
Example File1:
Fred Flintstone
Johnson Stone
Fred Flintstone
Fred Flintstone
Michael Clark
Desired Output File1:
Fred Flintstone
Johnson Stone
Fred Flintstone someString
Fred Flintstone
Michael Clark
Although you've mentioned sed
, these are sort of awk
-y tasks:
awk -v pat="Fred Flintstone" '$0 ~ pat {count++;\
if (count == 2) { $0 = $0" someString" ;} ;}; 1' file.txt
-v pat="Fred Flintstone"
saves the Regex pattern to match as variablepat
to be used insideawk
expressions$0 ~ pat
checks the record againstpat
for a match; if matched, thecount
variable is increased by 1 and ifcount
is 2 the record is reset as having the current content plussomeString
({count++; if (count == 2) { $0 = $0" someString" ;} ;}
)1 is an idiom; as it is truthy, all the records would be printed
Example:
% cat file.txt
Fred Flintstone
Johnson Stone
Fred Flintstone
Fred Flintstone
Michael Clark
% awk -v pat="Fred Flintstone" '$0 ~ pat {count++; if (count == 2) { $0 = $0" someString" ;} ;}; 1' file.txt
Fred Flintstone
Johnson Stone
Fred Flintstone someString
Fred Flintstone
Michael Clark
This simple sed
command allows you to selectively make the change without using loops (it does use a branch-to-end) or needing GNU extensions or reading the whole file at once:
sed -r '/Fred Flintstone/ {x; s/$/#/; /^#{2}$/ {x; s/.*/& someString/; b}; x}'
Explanation:
-
-r
- use extended regex -
/Fred Flintstone/
- for lines that match this pattern:-
x
- exchange pattern space and hold space (activate the counter) -
s/$/#/
- add a character to the counter -
/^#{2}$/
- when the counter is length 2 (substitute any value)-
x
exchange the pattern space and hold space (activate the counted input line) -
s/.*/& someString/
- append the string to the desired line -
b
- skip to the end of processing for this line so it can be printed
-
-
x
- exchange the pattern space and hold space (activate lines that match the string but not the count)
-
Indentation levels in the explanation indicate levels of curly brace nesting.
All other lines pass through without processing and are printed.