Reputation: 206
Using bash, I have this line of code that adds the content of a temp file into another file, after a specific match:
sed -i "/text_to_match/r ${tmpFile}" ${fileName}
I would like it to add the temp file content only after the FIRST match.
I tried using addresses:
sed -i "0,/text_to_match//text_to_match/r ${tmpFile}" ${fileName}
But it doesn't work, saying that "/" is an unknown command.
I can make addresses work if I use a standard replacement "s/to_replace/with_this/", but I can't make it work with this sed command.
It seems like I can't use addresses if my sed command starts with /
instead of a letter.
I'm not stuck with addresses, as long as I can insert the temp file content into another file only once.
Upvotes: 1
Views: 340
Reputation: 246744
You're getting that error because if you have an address range (ADDR1,ADDR2) you can't put another address after it: sed expects a command there and /
is not a command.
You'll want to use some braces here:
$ seq 20 > file
$ echo "new content" > tmpFile
$ sed '0,/5/{/5/ r tmpFile
}' file
outputs the new text only after the first line with '5'
1
2
3
4
5
new content
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
I found I needed to put a newline after the filename. I was getting this error otherwise
sed: -e expression #1, char 0: unmatched `{'
It appears that sed takes the whole rest of the line as the filename.
Probably more tidy to write
sed '0,/5/ {
/5/ r tmpFile
}' file
Full transparency: I don't use sed except for very simple tasks. In reality I would use awk for this job
awk '
{print}
!seen && $0 ~ patt {
while (getline line < f) print line
close(f)
seen = 1
}
' patt="5" f=tmpFile file
Upvotes: 3
Reputation: 5655
GNU sed also allows s///e
to shell out. So there's this one-liner using Glenn's tmpFile and file.
sed '0,/5/{//{p;s/.*/cat tmpFile/e}}' file
//
to repeat the previous pattern match (helps if it's longer than /5/
)p
to print the matching lines/.*/cat tmpFile/e
to empty the pattern buffer and stick a the cat tmpFile
shell command in there and e
execute it and dump the output in the streamUpvotes: 1
Reputation: 26471
Glenn Jackman provided with an excellent answer to why the OP's attempt did not work.
In continuation to Glenn Jackman's answer, if you want to have the command on a single line, you should use branching so that the r
command is at the end.
Editing commands other than
{...}
,a
,b
,c
,i
,r
,t
,w
,:
, and#
can be followed by a <semicolon>, optional <blank> characters, and another editing command. However, when ans
editing command is used with thew
flag, following it with another command in this manner produces undefined results.
[source: POSIX sed Standard]The
r,R,w,W
commands parse the filename until end of the line. If whitespace, comments or semicolons are found, they will be included in the filename, leading to unexpected results.
[source: GNU sed manual]
which gives:
sed -e '1,/pattern/{/pattern/ba};b;:a;r rfile' file
Upvotes: 2
Reputation: 1695
You have 2 forward slashes together, right next to each other in the second sed example.
Upvotes: -1