简体   繁体   中英

How to append entry the end of a multi-line entry using any of stream editors like sed or awk

I am trying to use a script to append the host name at the end of a multi-line entry of a specific Host_Alias field in sudoers file.

The current sudoers file has an entry similar to :

Host_Alias  srv_linuxestate= \
            host10,host12,host13,host1,host50,\
            host16,host1,host2,host11,host15,host21,\
            host3,host14

My required output would be something like the following where I have added ",host25"

Host_Alias  srv_linuxestate= \
            host10,host12,host13,host1,host50,\
            host16,host1,host2,host11,host15,host21,\
            host3,host14,host25

There are more lines before and after this segment.

The values for the hosts could change and is not fixed. Also there could be many more lines as above and these being separated using "\\" at the end of the incomplete line.

Any help/pointers would be great.

Here's a sed version:

/^Host_Alias/{                  # whenever we match Host_Alias at line start
:
/\\$/{N;b}                      # if backslash, append next line and repeat
s/$/,host25/                    # add the new host to end of line
}

If you need to add your new host to just one of the host aliases, adjust the first match to suit. In your example, it should probably be /^Host_Alias *srv_linuxestate=/ , or /^Host_Alias[ \\t][ \\t]*srv_linuxestate=/ if there might be tabs instead of spaces.

If you need it as a one-liner, that becomes sed -i -e '/^Host_Alias[ \\t][ \\t]*srv_linuxestate=/{;:;/\\\\$/{N;b};s/$/,host25/;}' /etc/sudoers .

Using awk with empty record separator:

awk -v RS= '$1=="Host_Alias" {$0 = $0 ",host25"} 1' /etc/sudoers
Host_Alias  srv_linuxestate= \
            host10,host12,host13,host1,host50,\
            host16,host1,host2,host11,host15,host21,\
            host3,host14,host25

This is assuming there is an empty line after last line of Host_Alias as in the regular sudoers file.

sed is for simple substitutions on single lines, that is all. All of the arcane sed constructs to do anything else became obsolete in the mid-1970s when awk was invented so just use awk:

$ awk '/Host_Alias/{f=1} f && !/\\/{$0=$0",host25"; f=0} {print}' file
Host_Alias  srv_linuxestate= \
            host10,host12,host13,host1,host50,\
            host16,host1,host2,host11,host15,host21,\
            host3,host14,host25

The above simply sets a flag when it finds a line containing Host_Alias and when that flag is set and the current line doesn't contain \\ it adds ,host25 to the end of the line and clears the flag.

Simple, clear, maintainable, efficient, portable, extensible, etc. etc. - better in every way than an equivalent sed solution.

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