How can I do a sed regex swap on all text that preceed a line matching a regex.
e.g. How can I d开发者_JS百科o a swap like this
s/foo/bar/g
for all text that precedes the first point this regex matches:
m/baz/
I don't want to use positive/negative look ahead/behind in my sed regex, because those are really expensive operations on big files.
If you mean that you want to do the substitution on every line preceding the given match, this is your answer:
The substitution takes an optional address range; you can use both numbers and patterns. In this case, start from line 1, go until your pattern:
sed '1,/baz/s/foo/bar/g'
In awk:
awk '
/baz/ { done = 1 }
{
if (!done) {
gsub(/foo/, "bar")
}
print
}'
(It's really short enough to leave out the line breaks, but they make it readable)
This variation on Jefromi's answer should do the trick of not touching the line that "baz" appears on as mentioned in Jonathan's comment.
sed '1,/baz/{/baz/!s/foo/bar/g}'
$ cat file
123 abc 01
456 foo 02 bar
789 ghi
baz
blah1
blah2
foo bar
$ awk -vRS="baz" 'NR==1{gsub("foo","bar")}1' ORS="baz" file
123 abc 01
456 bar 02 bar
789 ghi
baz
blah1
blah2
foo bar
baz
use "baz" record separator , then the 1st record will be the record you want to change "foo" to "bar".
with sed, variation of Denni's solution to take care of "baz" at first line
sed '0,/baz/{/baz/!s/foo/bar/g}' file
This might work for you:
awk '/baz/{p=1};!p{gsub(/foo/,"bar")};1' file
or this:
sed '/baz/,$!s/foo/bar/g' file
精彩评论