1

What can I do to remove the repeated code that happens during the second printf?

Surely there must be a more efficient way to add >> records.txt to the end of a printf without typing it again

if(($qs<=99999))
    then
        printf "${sp[x]} bonus is = £0 for ${qs[i]} QuarterlySales\n" 
        if [ $save == "y" ]
        then 
            printf "${sp[x]} bonus is = £0 for ${qs[i]} QuarterlySales\n" >> records.txt
        fi 
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
MONKAX
  • 11
  • 2
  • That's the wrong way to use `printf` -- the format string should be a separate argument from the actual values. `printf '%s bonus is = £0 for %s QuarterlySales\n' "${sp[x]}" "${qs[i]}"` – Charles Duffy Mar 30 '18 at 21:11
  • 1
    and btw, `[ $save == "y" ]` should be `[ "$save" = y ]`. There's no reason to quote the `y`, but quoting the expansion is essential; if `save='1 -o n'`, you'd get `[ 1 -o n == y ]`, so it would be true, even though the strings aren't even close to matching. And `==` isn't guaranteed to work in other implementations of `test`; only `=` [is standard-mandated](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html) as a string comparison operator. – Charles Duffy Mar 30 '18 at 21:11
  • Write yourself a log function that will conditionally append to a file – that other guy Mar 30 '18 at 21:12
  • Or you can conditionally redirect your script's stdout to `tee` up at the top of your script. We have other Q&A entries that tell you how to do that. `if [ "$save" = y ]; then exec > >(tee records.txt); fi` just once, and you've redirected every `echo`, `printf`, or other output line for your whole script. Closed as duplicative of an answer describing this. – Charles Duffy Mar 30 '18 at 21:13
  • Just save the string in a variable and echo it from there. And in (()) you don't need the $ in front of the variable name. Running tee (firing up another process) is overkill. – CrazyApe84 Mar 30 '18 at 21:16
  • BTW, repeating `>> records.txt` is actually quite inefficient -- you don't *want* to do it over and over for every line, since if you do, it's opening the file before running just one `echo` or `printf`, closing it afterwards, and then reopening it on the next line. `exec 3>>records.txt` just once at the top of your script (or `exec 3>records.txt` if you want the file to consist of the whole output of the run), and then you can use `>&3` whenever you want a command's output to go there without re-opening. – Charles Duffy Mar 30 '18 at 21:18
  • Similarly: `if [ "$save" = y ]; then exec 3> >(tee -a records.txt); else exec 3>&1; fi`, and then you can use `>&3` on any command you want to copy to `records.txt` *only if*`save` is set to `y`. – Charles Duffy Mar 30 '18 at 21:20
  • @CrazyApe84, `tee` isn't overkill if this is a long (or even modestly-sized) script. It's silly to double your number of `echo` or `printf` statements, unless that number is trivially small to start with. – Charles Duffy Mar 30 '18 at 21:21
  • I suppose you could have a function wrapper, if you really wanted to: `exec 3>>records.txt; log_cmd() { "$@"; if [ "$save" = y ]; then "$@" >&3; fi; }`, and thereafter `log_cmd echo "whatever"` -- but then you need to worry about whether someone uses the wrapper to invoke a command that's expensive to run or has side effects, rather than `echo` or `printf`. – Charles Duffy Mar 30 '18 at 21:25
  • @CharlesDuffy I amended your changes and since this isnt a very big script file I wont be using tee however I do get an error when I do it @CrazyApe84 way where it says command cannot be found `a=$(printf '%s bonus is = £0 for %s QuarterlySales\n' "${sp[x]}" "${qs[i]}") echo "$a" if [ "$save" == y ] then $a >> records.txt fi` This was a somewhat similar way I used in a previous version but couldnt get it to work due to errors. – MONKAX Mar 30 '18 at 21:48
  • `then $a` is trying to run the contents of your variable (the output you want to print) *as a command*. Should instead be something like `then printf '%s\n' "$a"`. Note that `a=$(printf ...)` is pretty expensive performance-wise on bash (it's much more efficient on ksh); on bash, better to run `printf -v a '%s bonus is = £0 for %s QuarterlySales\n' "${sp[x]}" "${qs[i]}"` to do the same thing. – Charles Duffy Mar 30 '18 at 22:13
  • See https://gist.github.com/charles-dyfis-net/4e5bd076b2790df92f9976b1b2b24eb3 – Charles Duffy Mar 30 '18 at 22:20
  • @CharlesDuffy This is much more seemless than what I had in mind. Thank you very much. Quick question, could you point me to how `"@"` works on the `run_to_log()` function? I would really appreciate it. – MONKAX Mar 30 '18 at 22:36
  • `"$@"` expands to the full argument list in the current context. See http://wiki.bash-hackers.org/scripting/posparams – Charles Duffy Mar 30 '18 at 23:35

0 Answers0