4

I have been give a command which outputs a comma-separated list for autosys jobs in the variable $all_jobs:

box=box-of-jobs;all_jobs=$(jobscout -box $box | egrep "^\w+" | tr '\n' ','  | sed s/.$//); 

I want to call a sendevent command for each item in the list:

sendevent -verbose -S NYT -E JOB_OFF_HOLD -J $job --owner me

So for example if $all_jobs evaluated job1,job2,job3

I want to call

sendevent -verbose -S NYT -E JOB_OFF_HOLD -J job3 --owner me
sendevent -verbose -S NYT -E JOB_OFF_HOLD -J job2 --owner me
sendevent -verbose -S NYT -E JOB_OFF_HOLD -J job1 --owner me

I'm sure I could write a ksh script to loop through, but I know these things can often be written much faster using awk/sed, both of which I'm not very familiar with so it's beyond my megre skills. I'm using ksh (rather than bsh).

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Ian
  • 53

3 Answers3

6

Splitting a string at a particular character is built into the shell at a very deep level: if you write $var without any surrounding quotes, then it is expanded as follows:

  1. Take the value of the var variable.
  2. Split this value into a list of fields. The field separator is any character in the value of the IFS variable. If IFS contains whitespace characters, then consecutive separators are considered as one; for non-whitespace characters, consecutive separators result in empty fields.
  3. Perform globbing, i.e. interpret each resulting field as a file name wildcard pattern. For each pattern that matches one or more files, replace it by the list of matching files.

The same happens for a command substitution $(somecommand), except that step 1 is “collect the output from running somecommand and strip all newlines at the end”.

To avoid all this rigmarole and just get the exact value of the variable, or the output of the command minus final newlines, be sure to put the variable substitution or command substitution between double quotes: "$foo", "$(foo)".

To split the result of a command susbtitution at comma characters, set IFS=, and leave the substitution unprotected. You need to do one more thing: turn off globbing, with set -f (and restore it afterwards with set +f.

all_jobs=$(…)
set -f; IFS=,
for job in $all_jobs; do
  sendevent -verbose -S NYT -E JOB_OFF_HOLD -J "$job" --owner me
done
set =f; unset IFS
  • Thanks - I tried to use IFS when I was googling for a solution before posting the question but I think I had the syntax slightly wrong - thanks for the example! – Ian Feb 08 '13 at 09:24
3

If you're sure that the fields between the commas do not contain any whitespaces than you could do something like this:

for job in $(echo $all_jobs | tr "," " "); do
    sendevent -verbose -S NYT -E JOB_OFF_HOLD -J "$job" --owner me
done

If you need something more robust, take a look at the tools needed to deal with CSV files under Unix.

rahmu
  • 20,023
  • Thank you - this worked perfectly (plus thanks for the further reading link). It doesn't need to be particularly robust - it's just a labour-saving device for setting things up - not production code. Thanks again! – Ian Feb 06 '13 at 15:03
0

You can use xargs:

all_jobs="job1,job2,job3"
echo $all_jobs | tr '\n' ' ' | xargs -d, --replace=xx sendevent -verbose -S NYT -E JOB_OFF_HOLD -J xx --owner me

The pipe through tr may not be needed if $all_jobs doesn't have a newline at the end

Renan
  • 17,136