1

Firstly, I can replace text in a text file using bash, the problem I have is that I have two pieces of text that need replacing but they are named the same but will require different information. So, to replace one piece of text is pretty simple, I just used (from users input):

clear
echo "Configuration of Radman properties file starting:"
read -p "Please enter the password utilised for radman in mysql configuration:" <password>
read -p "Please enter the password utilised for radius in mysql configuration:" <password>
VAR1="database.radman.datasource.password=<password>"
VAR2="database.radman.datasource.password=$<password>"
VAR3="database.radius.datasource.password=<password>"
VAR4="database.radius.datasource.password=$password>"
VAR5="/etc/radman/radman.properties"

sed -i.bak "s/${VAR1}/${VAR2}/g" ${VAR5}
sed -i.bak1 "s/${VAR3}/${VAR4}/g" ${VAR5}

But here is the issue I have with the second file (two databases):

sql raddb1 {
        dialect = "mysql"
        driver = "rlm_sql_${dialect}"
        #mysql {
        #        tls {
        #                ca_file = "/etc/ssl/certs/my_ca.crt"
        #                ca_path = "/etc/ssl/certs/"
        #                certificate_file = "/etc/ssl/certs/private/client.crt"
        #                private_key_file = "/etc/ssl/certs/private/client.key"
        #                cipher = "DHE-RSA-AES256-SHA:AES128-SHA"
        #                tls_required = yes
        #                tls_check_cert = no
        #                tls_check_cert_cn = no
        #        }
        #        warnings = auto
        #}
        server = "server1"
        port = 3306
        login = "radius"
        password = "<password>"

I need to change the "Server = " section and the "password = " section. This by itself is no problem. But there is a second database shown below:

sql raddb2 {
        dialect = "mysql"
        driver = "rlm_sql_${dialect}"
        #mysql {
        #        tls {
        #                ca_file = "/etc/ssl/certs/my_ca.crt"
        #                ca_path = "/etc/ssl/certs/"
        #                certificate_file = "/etc/ssl/certs/private/client.crt"
        #                private_key_file = "/etc/ssl/certs/private/client.key"
        #                cipher = "DHE-RSA-AES256-SHA:AES128-SHA"
        #                tls_required = yes
        #                tls_check_cert = no
        #                tls_check_cert_cn = no
        #        }
        #        warnings = auto
        #}
        server = "server2"
        port = 3306
        login = "radius"
        password = "<password>"

That has the same pattern. So if the user inputs the corect server name and password for raddb1 it will change it (as requried). But when they input the second set of variables, the pattern will be the same for raddb2. How can I change to the correct user input values for the same pattern in a single file? (This will only be the password as the server = is a different pattern for the two databases)

CliveG
  • 11
  • 3
  • `sed` sure isn't the best tool for the job; you'll have to write something more robust, with `awk` for example. Also, your code is a little confusing: I can't see any `database.radman.datasource.password=radpass` in the configuration file, and the values seem to be double-quoted but your `sed` commands don't add them (there's probably some kind kind of escaping to take into account). – Fravadona Apr 18 '22 at 12:26
  • The original bit of code I have written is to show it for a different file that works fine. It is purely an example of working code. – CliveG Apr 18 '22 at 13:06
  • For entering secret information (passwords), use the `-s` option for `read` – glenn jackman Apr 18 '22 at 13:41

2 Answers2

1

The examples you've shown are a little unclear but assuming the two separate configurations for raddb1 and raddb2 are in the same file you can use range specifiers with sed. You can specify a range in many ways. Please refer to the Addresses section of the sed manpage. And this stack post.

For your specific example something like this may work.

    radpass='1@3*773@11!*'
    sed "/sql raddb1/,/password = \"radpass\"/ s|password = \"radpass\"|password = \"$radpass\"|" input_file

The stack post linked above has a detailed explanation of the use of addresses with sed but basically the above command says to start looking for substitute matches after we match the first address /sql raddb1/ then stop looking after we match the second address /password = \"radpass\"/, which in this example is the same pattern in the substitute command. You can change the first address to match the next configuration block and so on.

BryanK
  • 1,211
  • 4
  • 15
  • 33
  • Apologies for late response. Been very busy. I will give your example a go BryanK and will get back to you. Very much appreciated. – CliveG Apr 20 '22 at 07:11
0

Bingo. Thanks BryanK. It is now working in two blocks of code as you suggested. here is the final result that worked perfectly:

clear
echo "configuration of <file> commencing. Please answer the questions that follow for correct detailed input:"
read -p "Please enter the primary server name (listed in /etc/hosts) for database1: " primary
read -p "Please enter the radius password utilised for accessing database1: " password
filename="/etc/raddb/mods-enabled/<filename>"
VAR1="test1"
VAR2="$primary"
VAR3="radpass"
VAR4="$password"
sed -i.bak4 "s/${VAR1}/${VAR2}/g" $filename
sed -i.bak5 "/sql raddb1/,/password = \"radpass\"/ s|password = \"radpass\"|password = \"$VAR4\"|" $filename

clear
echo "configuration of <file> continuing. Please answer the questions that follow for correct detailed input:"
read -p "Please enter the secondary server name (listed in /etc/hosts) for database2: " secondary
read -p "Please enter the radius password utilised for accessing database2: " password1
filename="/etc/raddb/mods-enabled/<filename>"
VAR5="test2"
VAR6="$secondary"
VAR7="radpass"
VAR8="$password1"
sed -i.bak "s/${VAR5}/${VAR6}/g" $filename
sed -i.bak5 "/sql raddb2/,/password = \"radpass\"/ s|password = \"radpass\"|password = \"$VAR8\"|" $filename

I think with your solution, I probably do not need VAR3 and VAR7, but it works a treat. Thank you.

CliveG
  • 11
  • 3
  • Incidentally I'd recommend not calling your vars `VARn`, but giving them real names. Here `VAR5` might be `pattern` for instance. Readability matters, *especially* in bash. – 2e0byo Apr 20 '22 at 08:14
  • Consider accepting my answer if it helped. I think your question can be better phrased to something like "how to search and replace text in a file within a specified range" as well. – BryanK Apr 27 '22 at 14:35