在bash中处理来自文件/ cli / stdin的参数

时间:2011-08-04 23:36:14

标签: bash shell cron config

我可以看到自己最终编写了很多脚本,这些脚本根据命令行上的一些参数做了一些事情。

然后通过调度程序自动执行多次或多或少相同的操作。

为了防止自己不得不为参数的每个变体创建一个新作业,我想创建一个简单的脚本框架,我可以用它来快速创建脚本,这些脚本采用相同的参数:

  • 命令行
  • 来自命令行
  • 上指定的路径的文件
  • 从stdin到eof

我从TAB delim文件中获取参数或配置的初始方法如下:

if [ -f "$1" ]; then
    echo "Using config file '$1'"
    IFS='   '
    cat $1 | grep -v "^#" | while read line; do
            if [ "$line" != "" ]; then
                    echo $line
                    #call fn with line as args
            fi
    done
    unset IFS
elif [ -d "$1" ]; then
    echo "Using cli arguments..."
    #call fn with $1 $2 $3 etc...
else
    echo "Read from stdin, ^d will terminate"
    IFS='   '
    while read line; do
            if [ "$(echo $line | grep -v "^#")" != "" ]; then
                    #call fn with line as args
            fi
    done
    unset IFS
fi

所以那些无疑以前做过这种事的人:

  1. 你是怎么做的?
  2. 我是否过于程序化 - 用awk或类似的方法可以做得更好吗?
  3. 这是最好的方法吗?

2 个答案:

答案 0 :(得分:3)

您能想到一个符合您描述的标准Unix实用程序吗? (不,我不能。)这表明你的目标略微偏离目标。

-f "$1"-d "$1"的测试并不常见,但如果您的脚本仅适用于目录,则可能有意义。

最终,我认为你需要一个像:

这样的界面
your_cmd [-f argumentlist] [file ...]

显式但可选-f argumentlist允许您在命令行中指定要读取的文件。否则,将处理在命令行上指定的文件,除非没有此类参数,在这种情况下,将从标准输入读取要处理的文件名。这与传统组织更接近。我们可以讨论在其他时间用名称中的空格和换行符处理文件名。

您的代码核心将被编写为一次接受/处理一个文件名。这可以写成shell函数,允许最大程度的重用。

while getopts f: opt
do
    case $opt in
    (f) while read file; do shell_function $file; done < $OPTARG; exit 0;;
    (*) : Error handling etc;;
    esac
done
shift $(($OPTIND - 1))
case $# in
(0) while read file; do shell_function $file; done; exit 0;;
(*) for file in "$@"; do shell_function $file; done; exit 0;;
esac

对此进行调整并不是很难。它也相当紧凑。

答案 1 :(得分:3)

不确定我是否有点广泛,但听起来你正试图重新发明xargs。

如果您有脚本,通常会这样调用

$ your_script.sh -d foo bar baz

您可以按如下方式从stdin获取参数:

$ xargs your_script.sh
-d foo
bar
baz
^D

我们来自档案

$ cat config_file | xargs your_script.sh

(假设config_file具有以下内容)

-d foo bar 
baz

或来自多个配置文件

$ cat config_file1 config_file2 | xargs your_script.sh