简体   繁体   中英

Bash - Find and replace with new lines in the same file

I need to find a line in a file that contains a specific variable name. This variable may be commented or not. If not commented then I need to comment it. Add two lines afterwards. The first line begins with a comment on why the addition of the new line then the new line of the variable with attach value. I'm using ubuntu 14.04.01 x64 and it has version (GNU sed) 4.2.2 and GNU Awk 4.0.1 . Also I would like to use variable defined earlier in the script. So command needs to be accept reference to those variables. Also do not output the result to console. Some examples are:

Case 1

#ssh_param /path/to/file

Results

#ssh_param /path/to/file

#New path defined
ssh_param /etc/ssh/file

Case 2

ssh_param /path/to/file

Result

#ssh_param /path/to/file

#New path defined
ssh_param /etc/ssh/file

Case 3

#ssh_param 

Results

#ssh_param 

#New path defined
ssh_param /etc/ssh/file

Case 4

#ssh_param dasfda
ssh_param /path/to/file

Results

#ssh_param dasfda
#ssh_param /path/to/file 

#New path defined
ssh_param /etc/ssh/file

You can use this awk:

awk 'index($0, "ssh_param /path/to/file"){if (substr($0, 1, 1) != "#") $0 = "#" $0;
       $0=$0 "\n\n#New path defined\nssh_param /etc/ssh/file"} 1' file

To change fil content:

awk 'index($0, "ssh_param /path/to/file"){if (substr($0, 1, 1) != "#") $0 = "#" $0;
       $0=$0 "\n\n#New path defined\nssh_param /etc/ssh/file"} 1' file > file.tmp
mv file.tmp > file

You wanted to use "variables defined earlier in the script." Here are the variables:

file="path/to/input/file"
var="ssh_param"
msg="#New path defined"
new="/etc/ssh/file"

Here are the commands which use those variables:

lineno=$(grep -n "$var" "$file" | tail -n1 | sed 's/:.*//')
if [ "$lineno" ]
then
    sed -i -r "$lineno s|#?(.*)|#\1\n$msg\n$var $new|" "$file"
else
    sed -i -r "$ s|$|\n$msg\n$var $new|" "$file"
fi

Notes:

  • It appears from your examples that the variable name may occur multiple times in the script but only the last one is uncommented. We use that here to simplify the code. The line number of the last appearance of the variable in the script is found from:

     lineno=$(grep -n "$var" "$file" | tail -n1 | sed 's/:.*//') 

    The grep -n part finds a list of line numbers on which the variable name occurs. tail -n1 returns only the last such line. The sed command removes all but the line number from the output.

  • The substitution is done by this command:

     sed -i -r "$lineno s|#?(.*)|#\\1\\n$msg\\n$var $new|" "$file"` 

    This uses sed's ability to operate on a particular line number. That line is substituted by three lines: the first is a copy of the existing line but commented, the second is the message, and the third is the new definition of the variable.

  • If the variable is not currently in the file, then lineno is empty. In this case, we want to add the new lines to the end of the file. This is done via a similar but simpler sed command:

     sed -i -r "$ s|$|\\n$msg\\n$var $new|" "$file" 

The first $ tells sed to operate only on the last line. The second $ appears in the substitute command where it signifies the end of that line. Your message and new variable definition are appended.

Example

With this as the input:

#ssh_param dasfda
ssh_param /path/to/file

The above code replaces the file with:

#ssh_param dasfda
#ssh_param /path/to/file
#New path defined
ssh_param /etc/ssh/file

(If you want blank lines to space things out, just add some \\n to the sed output expression.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM