1

Put as simply as possible, In Linux with bash/sed/awk and basic OS commands, I am attempting to create a list with multiple headings in a text file, with a bunch of strings underneath them (servernames). I then hope to be able to have a script go and run various tasks on each of the entries under a specific heading that I pass as an option/parameter at runtime.

Example of what this text file would look like: (these entries should be ordered UNDER the header in question in a single column, I just can't get it to display that way on this page.)

[main_server_list]
Jupiter
Saturn
Thisguy
Thatguy
BuffalO
randomspite
coffeebinge

[alternate_server_list]
Jupiter
Saturn

[Tertiary_server_list]
Thisguy
Thatguy
coffeebinge

[Enough_already]
BuffalO
randomspite

So basically, if I wanted to copy a file to a directory to ALL of my machines, I would want to do something like:

   # bash maincopyscript.sh [main_server_list]

And the "loop" would know that the list of servers to install this on would be every entry under the [main_server_list] header, but ignore everything else under any other header.

Similarly, I also want to be able to do:

   # bash maincopyscript.sh [Tertiary_server_list]

And expect the same functionality, only this time, only run the "loop" on entries under the [Tertiary_server_list] header, and then be finished.

Lastly, I would like to be able to specify multiple headers if I wish as well, specified in any order. Such as:

   # bash maincopyscript.sh [Enough_already] [alternate_server_list]

It should then run the operations specified in the script on only the entries under those 2 headers, and then be finished.

Hopefully you get the idea, basically a way to do this utilizing bash/sed/awk mainly. (or even another tool if necessary)

Yes yes, I understand that ansible/puppet/chef can also help me achieve these results, but I have specific reason for wanting to do this regardless. I tried to search for an hour or 2 for any pre-existing post on this, but couldn't find one, so finally decided to ask my question. Any help would be appreciated!

(Bonus, if anyone could also show me how to put entries under each header in alphabetical order while keeping the headers and groups themselves in the exact same formations that would be great too!)

  • Thanks for the list fix ilkkachu. Now hopefully someone has an answer! – Viscosity Aug 9 '16 at 16:03
  • Hint: there's a little question mark hidden in the upper right corner of the editor, behind it is the help for the markup. :) – ilkkachu Aug 9 '16 at 16:15
1

You could pull the names from under a heading with, say awk and toss them in an array variable, then iterate over the array with for. The script here takes the pattern from the command line.

#!/bin/bash
patt=$1
if [ -z "$patt" ] ; then echo "need an argument" ; exit 1 ; fi
A=( $(awk '/^\[/ {p = 0};
           /^\['"$patt"'\]/ {p=1; next}
           p && !/^ *$/ ;' < servers )  )

for x in "${A[@]}" ; do 
    echo doing something with "$x" 
done

So,

$ bash for_all.sh alternate_server_list
doing something with Jupiter
doing something with Saturn

In the awk program:
/^\[/ {p = 0} - set p to zero if an open bracket is the first character on the line,
/^\['"$patt"'\]/ {p=1; next} - if we match the pattern, set p to one and skip to next line. Note, the pattern is given to awk from the shell variable, so it will be taken as a regular expression. The quotes are a bit funny, because there's part of the code in single-quotes, then the variable in double-quotes, and then more code in single-quotes. like 'foo' "$var" 'bar' but without the spaces.
p && !/^ *$/ - if p is set and the line isn't empty (only spaces between start and end), print it (default action).


Oh, and, this will crash and burn if your list items contain anything funny, like spaces.

  • Ikkachu, I tested it, and this works pretty perfectly even with some of my own modifications. It also, addresses almost everything! The only 2 additional things I need it to do would be to: 1. Be able to take more than one argument(header) at a time and process all of them. 2. If a header has no values below it, and/or is non-existent in the text file, the script should point out this fact on that particular argument that was supplied, but then continue to parse any additional arguments that follow. If those two final elements could be included that would be fantastic! – Viscosity Aug 9 '16 at 17:48
  • I'll work on the 2 additional issues myself (previous reply above) as well now that I have a basis, but I would naturally welcome anyone's assistance in making these 2 final elements function. – Viscosity Aug 9 '16 at 17:49
  • Good! As a pointer, if you didn't already find it, look up "positional parameters", they should be what you'll need. – ilkkachu Aug 9 '16 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.