0

I have a function plist that is able to call head and tail commands. But for processing regions I call a different function pregion.

# --- plist ---

  ("-H"|"--head")
    local -r hn="$2" ; shift 2 ;;
  ("-T"|"--tail")
    local -r tm="$2" ; shift 2 ;;

  ("--FS")                           # field separator
    local fs="$2" ; shift 2 ;;
  ("--incl")
    local incl+=("$2") ; shift 2 ;;  # file type suffix
  ("--excl")
    local excl+=("$2") ; shift 2 ;;  # file type suffix

  ("--RP")
    local pn=$2 ; shift 2 ;;
  ("--RQ")
    local qn=$2 ; shift 2 ;;

  ("--dyn"|"--dynamic")
    local dyn="1" ; shift 1 ;;
  ("-C"|"--context")
    local ctx=$2 ; shift 2 ;;

  ("-d"|"--directory")
    local fdir=$2 ; shift 2 ;;

  (--)
    shift;  break  ;;

  ...

  if [[ -v hn ]]; then

     head -v -hn "$n"
    
  elif [[ -v tm ]]; then

    tail -v -n "$tm"

  elif [[ -v dyn ]]; then

    pregion "$@"  # requires original options here

  fi

With head and tail, I only use options -H, -T', --FS, and --incl. Because I am using shift when processing options, I need to have a copy ef the original plist input arguments, because I cannot simply pass "$@" to pregion.

This will call head or tail

  plist -H 8 ./01cuneus

  plist -T 13 ./01cuneus

Examples of calling pregion

plist --dyn -C 8 "Martin" ./01cuneus

plist --incl .texi --incl .org --RP 8 --RQ 13 ./01cuneus

plist --incl .texi --incl .org --dyn -C 8 "Martin" ./01cuneus
10
  • 1
    I don't understand your question at all. There's no shift in this code. I don't see -H, -T etc. Why do you think you can't pass the args to pregion? You can make a copy of the incoming params to plist (args=("$@")) and use that to pass to pregion (pregion "${args[@]}") Jul 27, 2021 at 12:57
  • Can you modify that into a complete script showing this particular issue with the arguments? Include the interesting stuff about arguments, the way you process them, including the shift. What the problem is in passing "$@" as arg to pregion. Everything related to this issue. And rip out the parts that are irrelevant to this, if running head is not where the problem is, just remove it or replace with an echo "this is where we'd call head / do this or that" or so.
    – ilkkachu
    Jul 27, 2021 at 12:59
  • @glenn I did not include the options part, because passing arguments and setting variables in functions is customarily straighforward. This simply focuses on passing the original options list intact because I call shift whilst processing tho arguments for head and tail in function plist.
    – Pietru
    Jul 27, 2021 at 13:01
  • (also how you're meaning the function should work, i.e. if called as plist foo bar, then do this, but if called with plist -x -y abcd, then do this.)
    – ilkkachu
    Jul 27, 2021 at 13:03
  • 1
    Just use pregion --dyn -C 8 "Martin" ./01cuneus, etc. if that's what you want.
    – rowboat
    Jul 27, 2021 at 13:36

2 Answers 2

0

Copy the orginal args to an array, and use that with pregion. e.g.

plist() {
  local -a origargs=("$@")
  ...
  case
    ...
  esac
  ...

  if
    ...
  elif [[ -v dyn ]]; then
    pregion "${origargs[@]}"
  fi
1
  • Have figured out that the problem was being produced by an incorrect call using pregion "$origargs".
    – Pietru
    Jul 27, 2021 at 13:58
0

You could indeed save the contents of $@ to an array

plist() {
    local args
    args=("$@")
    case $1 in ...
        # some shifting etc.
    esac
    if something; then
        pregion "${args[@]}"
    fi
}

But, that would mean that pregion would need to do the whole option processing again. In effect, you'd implement the same process in two places. And what about returning errors for invalid options from plist? You couldn't do that before figuring out if you're going to call pregion, since it might accept some options plist doesn't.

Instead, I'd suggest doing the option parsing only once, and then calling pregion with the appropriate values already parsed to individual arguments:

plist() {
    local args
    args=("$@")
    local this=default that=otherdefault
    local call_pregion=
    case $1 in ...
        this) this=$2; shift; shift;;
        that) that=$2; shift; shift;;
        dyn) call_pregion=1
    esac
    if [ "$call_pregion" ]; then
        pregion "$this" "$that"
    fi
}

that way pregion can just take the values from static positions in the list, e.g. $1 for $this and $2 for $that.

Also, btw, using shift 2 there is risky. Depending on the shell it may silently fail there aren't enough arguments to shift. E.g. set a b c; shift 4; echo $1 will exit with an error in Dash, but in Bash, it'll happily just print a. That may leave your option parsing stuck in a loop if the user gives an option without the corresponding option-argument.

5
  • I fail to see how your comment on shift 2 can be resolved with shift ; shift ;;. when there aren't enough arguments to shift.
    – Pietru
    Jul 27, 2021 at 14:05
  • @Pietru, if you're looping until all the arguments are gone, you'll want to remove the ones you've processed. With just one arg, shift 2 leaves it there. E.g. you're looking at -H, then shift 2 does nothing, and the next time you're looking at the same -H again. In shift; shift, they work individually, and the first removes the first arg, regardless of if the second will fail since there is no other arg. Try e.g. foo() { while [ "$1" ]; do case $1 in (-x) x=$2; shift 2;; esac; done; echo "x: $x"; } vs. the same with shift; shift instead. Run with foo -x test and foo -x.
    – ilkkachu
    Jul 27, 2021 at 14:14
  • Does shift fail when it encounters -this or --that ?
    – Pietru
    Jul 27, 2021 at 15:00
  • Have done local rp=$2 ; shift ; shift followed by echo "\$@: $@" ;;. Running plist --dyn --RP --RQ 8 "John" ./01cuneus gave $@: -- 8 John ./01cuneus. With plist --dyn --RP 5 --RQ 8 "John" ./01cuneus, I got $@: --RQ 8 -- Behistun ./01cuneus. Seems to imply that calling shift ; shift behaves as shift 2.
    – Pietru
    Jul 27, 2021 at 16:36
  • @Pietru, try it without giving an argument to --RP or --RQ. Something like just plist --dyn --RP 5 --RQ.
    – ilkkachu
    Jul 27, 2021 at 18:52

You must log in to answer this question.

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