matejak / argbash

Bash argument parsing code generator
Other
1.4k stars 62 forks source link

recursion: parse arguments from file #158

Closed milahu closed 2 years ago

milahu commented 2 years ago

gcc has this option:

@file

Read command-line options from file. The options read are inserted in place of the original @file option. If file does not exist, or cannot be read, then the option will be treated literally, and not removed.

Options in file are separated by whitespace. A whitespace character may be included in an option by surrounding the entire option in either single or double quotes. Any character (including a backslash) may be included by prefixing the character to be included with a backslash. The file may itself contain additional @file options; any such options will be processed recursively.

(gcc/Overall-Options.html)

so the @my-args.txt argument is expanded / replaced with the contents of the my-args.txt file

my use case: i made my own parser generator, generated from gcc's opt files, to parse a subset of gcc options in gcc-options-parser ... now im looking for a cheap way to implement the "parse arguments from file" feature

challenge: string parsing → shlex in python

cheap solution: eval

#! /usr/bin/env bash

args=("$@")
argsLen=${#args[@]}
argsParsed=()
for (( i=0; i<$argsLen; i++ ))
do
  a="${args[$i]}"
  case "$a" in
    @*)
      argsFile="${a:1}"
      [ ! -e "$argsFile" ] && { echo "error parsing option $a: no such file"; exit 1; }
      eval fileArgs=( $(cat "$argsFile") ) # WARNING eval is unsafe
      args=( "${args[@]:0:$i}" "${fileArgs[@]}" "${args[@]:$((i + 1))}" ) # replace the @file argument
      argsLen=${#args[@]} # update length
      : $((i--)) # re-parse the replaced argument
    ;;
    *)
      argsParsed+=("$a")
    ;;
  esac
done

for (( i=0; i<${#argsParsed[@]}; i++ ))
do
  echo "$i: ${argsParsed[$i]}"
done
matejak commented 2 years ago

This is slightly beyond the scope of Argbash, although if the feature was cheap, it would make sense. Having an eval that executes contents of a runtime-supplied file is too much.