Being able to work with the command line in Linux and use tools such as sed can be really powerful. We show you how you can match only the first occurrence of a string or regular expression using sed in Linux with Ubuntu. The example we use will be replacing the first time server only in the chrony.conf on an Ubuntu 14.04 Linux server. This though could be any system so long as we are using the GNU Linux sed command.
Using Linux SED to Search
First, let’s use sed to search for server entries in the configuration file. Sure we can use grep for this but we will stick with sed as we eventually want to edit the file with sed.
root@drbd-alice:~# sed -n '/^server/p' /etc/chrony/chrony.conf server 0.debian.pool.ntp.org offline minpoll 8 server 1.debian.pool.ntp.org offline minpoll 8 server 2.debian.pool.ntp.org offline minpoll 8 server 3.debian.pool.ntp.org offline minpoll 8 root@drbd-alice:~#
With sed, the -n option suppresses printing of the complete file and the p command is used to print the matching pattern.
We would like to replace the first entry with a custom entry of our own. We will also add in the prefer option to ensure that this is used for synchronisation as long as it is available. Using this method we can sync with our own local NTP server whilst maintaining the other as failover backups.
Matching the First Line Only
We want to match the first occurrence only with sed. When we come to replace the entry it is only the first match line that we want to edit. Now we could extend the regular expression to include the server name but then we would need to check the entries first and adjust accordingly. We want a full proof method of editing the first matching line only with sed.
sed -n '/^server/ {p;q}' /etc/chrony/chrony.conf server 0.debian.pool.ntp.org offline minpoll 8 root@drbd-alice:~#
Here the result is achieved with the same search but using q to quit of the first match. We will need to adjust this thought to be able to replace text.
Adjusting the Search to Support Editing
root@drbd-alice:~# sed -n '0,/^server/s/\(^s.*\)/server 172.16.0.3 prefer iburst/p' \ /etc/chrony/chrony.conf server 172.16.0.3 prefer iburst root@drbd-alice:~#
We now specify to match the first matching server line with 0,/^server/. Zero being the first matching line or index 0. We then want to substitute s the entry starting with s followed by at least one character .* This is the way of substituting the complete line without laboriously typing in the complete line. We also have to group this in parenthesis. The brackets have to be escaped using the backslash. We end up adding in s/\(^s.*\)/ for the complete text to replace. We next add the replacement text, in my case I want to sync with 172.16.0.3 so we replace then line with server 172.16.0.3 iburst prefer.
At this stage, we are still only printing the result but not editing the file.
Editing the File
If we remove the p command at the end of the string and replace the -n option with -i, we then edit the file. If you are certain your result from printing is ok we can edit the file with the following command.
# sed -i '0,/^server/s/\(^s.*\)/server 172.16.0.3 prefer iburst/' /etc/chrony/chrony.conf
There will be no output from this command but your file will have been edited. Please stay for the video demonstration where all will be explained.
More sed videos: https://www.theurbanpenguin.com/sed-inserts-deletes-and-appends/