2

I'd like to replace one string from one file with a string from another file. Though I'm not experienced with these commands, I expect some combination of grep and sed would do it best.

What makes this a bit more complicated is that I don't know what either string is (I'm trying to automate replacing the version number on my documentation). I do know that in both cases the string I'm looking for (say "2.3.4") is preceded by "version:"

So can I say 'look for word (or rest of line or whatever is possible) after "version:" (let's call it string1) and do the same in another file (giving string2) and replace string string1 with string2.

Here are some example text files:

file1.txt

This is a file containing
the updated version number.
version: 2.3.4
here is a string with more info

file2.txt

This is a configuration file
It could contain an old version number
version: 2.3.2
Please update this

So the expected output for file2.txt would become:

file2.txt

This is a configuration file
It could contain an old version number
version: 2.3.4
Please update this

Thanks

4
  • Can you please give us some input?? Commented Jul 18, 2012 at 8:28
  • 1
    It is rare to find a situation where you need both grep and sed. If grep is powerful enough, you don't need sed, and if not, sed can do almost everything grep can do (albeit sometimes it gets tortured). Commented Jul 18, 2012 at 8:40
  • can u plz share the expected output for the same .... so dat we can think over the solution ... Commented Jul 18, 2012 at 8:53
  • Sure thing. See original question Commented Jul 18, 2012 at 10:20

2 Answers 2

2

Provided you have a sed which supports the -i option,

sed -i 's/version: .*/version: 1.2.3/' file1 file2 file3 ...

You may want to tweak the regex wildcard; .* matches through the end of the line, whereas [.0-9]* matches the longest possible sequence of dots and digits. You might also want to permit for variations in surrounding whitespace ... But since this is probably among the top 10% FAQs on this site, go look for similar questions at this point.

To obtain the replacement string from file1 and apply it to file2, file3, etc, something like

new=$(sed -n 's/version: //p' file1)
# Use double quotes, not single, in order to expand $new
sed -i "s/version: [.0-9]*/version: $new/" file2 file3 ...

The first sed invocation will only print lines on which "version: " was found and removed (replaced with an empty string). Presumably there will only be one such line in the file. Pipe the output to head -n 1 or uniq or something, or find / create a more elaborate sed script.

You normally use single quotes around literal strings, but since you don't want a literal $new in the replacement, we use double quotes, which allow the shell to perform variable replacement (and a number of other substitutions we don't go into here) in the quoted string.

Sign up to request clarification or add additional context in comments.

6 Comments

I don't think the new version is known.
Yeah, sorry if I didn't make that clear. Neither version number is known, since they are regularly updated, and I'd ideally not want to have to manually change this script with each version change.
Thanks for your response. When I run this I find that the whole of file1 is inserted into file2 in place of the version number line. So I'm guessing that something's up with the variable new that means it doesn't take one line only
@ tripleee It appears the problem is with the -n command, which doesn't work with mac's bash. I can't seem to find a work-around. If you know of one that would be a big help.
Try sed '/version: /!d;s///' file1
|
2

is this ok for you?

kent$  head f1 f2
==> f1 <==
This is a file containing
the updated version number.
version: 2.3.4
here is a string with more info

==> f2 <==
This is a configuration file
It could contain an old version number
version: 2.3.2
Please update this

kent$  awk 'NR==FNR{if($0~/^version:/){x=$0;} next;}{gsub(/^version:.*$/,x);print $0}' f1 f2
This is a configuration file
It could contain an old version number
version: 2.3.4
Please update this

4 Comments

Using exactly what you've written my f2.txt remains with the old version number. In the command line all of the files are printed in one long line (i.e. they don't keep their formatting). I'm afraid I'm unfamiliar with awk. Does this command make the change to the file, or just to the printed text?
@user1488804 as you saw in my answer, it worked here. here is gawk 3.1.6 on linux. the awk line above wouldn't change your file2, it print the output on console.
Ok. So the awk command isn't transferable then? (I'm using Mac command line). And how could the code be changed to cause the version update to actually change the text file? Thanks
@user1488804 you can simply do 'cmd>tmpfile' to get the output in file. then you have many ways to change your original file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.