3

I'm using Dash because this is to run on my rPi. Bash is not an option.

I'm rewriting a Bash script to work with Dash. I'm hoping to make it as POSIX-compliant (portable) as possible. The thing is it's difficult to find help on how to do loops through multi-line strings that don't involve Bash.

My script works up until I reach a point where I have to go through a list of 100 to 1000 devices, each on their own line in a text file. For example, the file could look similar to:

foo
bar
device
blah

I'm importing the words using a simple cat command: LIST="$(cat $2)". From here I need to loop through each word in $LIST:

for ARRAY in ${LIST}
do
    printf "Getting VLANS for: $ARRAY"

    VLANS=$(snmpbulkwalk -v 2c -t 2 -r 3 -c "$COMMUNITY" "$ARRAY.dcs.byu.edu" XIRRUS-MIB::vlanName -Oqv)
    printf "$ARRAY,$VLANS" >> "$REPORT"
done

When the loop begins $ARRAY pretty much prints out everything that $LIST has, effectively making it pointless. It is vital that only one word is stored in $ARRAY since snmpbulkwalk can only handle one device at a time. It will return all data as one multi-line string, however this can be easily handled using sed to replace each newline with a comma.

So, what is a proper and/or effective method of iterating through each word in a string? Arrays, from what I understand, are fairly non-existant in Dash, making mutations a little more difficult. I've tried using the Ubuntu guide and this very helpful reference. As I'm writing this I'm beginning to think that I may have to try to use grep to read line-by-line and nest another for-loop but I'm unsure if there's a more simple, "clean" way.


You guys are fantastic! Quick, clean responses and some examples.

So, I created two different versions of the script, both of which work perfectly. The first was done as roaima outlined and was also suggested by steeldriver. I replaced my loop with a while that would instead read my file line-by-line. Thank you for that, this certainly helps simplify things and shows that arrays were not necessary in my case.

My second version simply replaced printf "Getting VLANS for: $ARRAY" with echo "Getting VLANS for: $ARRAY" and eventually I just removed it to see what would happen. Somehow this made all the difference: ARRAY did not contain everything that was in LIST which allowed the rest of the code to work properly. If someone wants to further clarify on how this worked please do so in the comments.

Thanks again guys! It's working much faster than it did before on Bash. A few more tweaks to parse the data from snmp is all that's left!

8
  • 1
    Do you really need LIST at all? can you not just read lines from the file directly, using a while loop? Apr 22, 2015 at 23:58
  • Are you sure that ARRAY has more than one word? printf doesn't put a newline by default, meaning that this script will print all output on the same line. Try replacing printf by echo, and see if that changes anything.
    – Ringstaart
    Apr 23, 2015 at 0:00
  • @steeldriver That's part of what I'm asking myself, having reduced so much of this from the Bash-style we had it seems redundant now. I could do read from the file line-by-line. I assume it would be fairly quick and easy? Apr 23, 2015 at 0:07
  • @Ringstaart Somehow it started to work with echo, leaving parsing to be the only issue to deal with. How the heck? I had to remove that earlier when changing code because it kept printing everything as a huge list Apr 23, 2015 at 0:14
  • If you use printf, it doesn't print a newline. The next thing that's printed will end up on the same line. echo automatically appends a newline, which is desirable in most cases. If you don't need everything to be on the same line, echo is usually the best choice.
    – Ringstaart
    Apr 23, 2015 at 0:17

1 Answer 1

3

This is how I would read a line at a time from a file

while IFS= read -r DEVICE
do
    ....
done < your_file
5
  • I'll try that. Question though about the redirects, with your last line done < your_file will that output to a file and simply concatenate to the end of what's already in the file? Or will it just overwrite what is already in it? If it overwrites then I assume I should just store everything into a single variable before dumping it out to a file Apr 23, 2015 at 0:09
  • @Kamikaze Rusher; < is redirecting standard input from the given file.
    – Janis
    Apr 23, 2015 at 0:18
  • @Janis Ah, ok. So the while IFS= read -r DEVICE is given input that is redirected/passed from your_file? Apr 23, 2015 at 0:22
  • @Kamikaze Rusher; yes, exactly.
    – Janis
    Apr 23, 2015 at 0:23
  • @Janis thank you so much! The mix of syntax is rather confusing at times... Apr 23, 2015 at 0:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .