Lee Exothermix
Lee Exothermix

Reputation: 356

linux bash insert text at a variable line number in a file

I'm trying to temporarily disable dhcp on all connections in a computer using bash, so I need the process to be reversible. My approach is to comment out lines that contain BOOTPROTO=dhcp, and then insert a line below it with BOOTPROTO=none. I'm not sure of the correct syntax to make sed understand the line number stored in the $insertLine variable.

    fileList=$(ls /etc/sysconfig/network-scripts | grep ^ifcfg)
    path="/etc/sysconfig/network-scripts/"
    for file in $fileList
    do
        echo "looking for dhcp entry in $file"
        if [ $(cat $path$file | grep ^BOOTPROTO=dhcp) ]; then
            echo "disabling dhcp in $file"
            editLine=$(grep -n ^BOOTPROTO=dhcp /$path$file | cut -d : -f 1 )
            #comment out the original dhcp value
            sed -i "s/BOOTPROTO=dhcp/#BOOTPROTO=dhcp/g" $path$file
            #insert a line below it with value of none.
            ((insertLine=$editLine+1))
            sed "$($insertLine)iBOOTPROTO=none" $path$file
        fi
    done

Any help using sed or other stream editor greatly appreciated. I'm using RHEL 6.

Upvotes: 0

Views: 120

Answers (2)

dash-o
dash-o

Reputation: 14468

The sed editor should be able to do the job, without having to to be combine bash, grep, cat, etc. Easier to test, and more reliable.

The whole scripts can be simplified to the below. It performs all operations (substitution and the insert) with a single pass using multiple sed scriptlets.

#! /bin/sh
for file in $(grep -l "^BOOTPROTO=dhcp" /etc/sysconfig/network-scripts/ifcfg*) ; do
   sed -i -e "s/BOOTPROTO=dhcp/#BOOTPROTO=dhcp/g" -e "/BOOTPROTO=dhcp/i BOOTPROTO=none" $file
done

As side note consider NOT using path as variable to avoid possible confusion with the 'PATH` environment variable.

Upvotes: 1

David C. Rankin
David C. Rankin

Reputation: 84579

Writing it up, your attempt with the following fails:

sed "$($insertLine)iBOOTPROTO=none" $path$file

because:

  • $($insertLine) encloses $insertLIne in a command substitution which when $insertLIne is evaluated it returns a number which is not a command generating an error.
  • your call to sed does not include the -i option to edit the file $path$file in place.

You can correct the issues with:

sed -i "${insertLine}i BOOTPROTO=none" $path$file

Which is just sed - i (edit in place) and Ni where N is the number of the line to insert followed by the content to insert and finally what file to insert it in. You add ${..} to insertLine to protect the variable name from the i that follows and then the expression is double-quoted to allow variable expansion.

Let me know if you have any further questions.

(and see dash-o's answer for refactoring the whole thing to simply use sed to make the change without spawning 10 other subshells)

Upvotes: 0

Related Questions