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

在bash中处理文件/cli/stdin中的参数,bash,shell,cron,config,Bash,Shell,Cron,Config,我可以看到自己最终编写了很多脚本,这些脚本根据命令行上的一些参数做了一些事情 然后,这就发展到使用调度程序多次自动执行或多或少相同的操作 为了避免自己必须为参数的每个变体创建新作业,我想创建一个简单的脚本框架,我可以使用它快速创建脚本,这些脚本从以下位置获取相同的参数: 命令行 来自命令行上指定路径的文件 从stdin到eof 我最初从TAB delim文件获取参数或配置的方法如下: if [ -f "$1" ]; then echo "Using config file '$1'"

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

然后,这就发展到使用调度程序多次自动执行或多或少相同的操作

为了避免自己必须为参数的每个变体创建新作业,我想创建一个简单的脚本框架,我可以使用它快速创建脚本,这些脚本从以下位置获取相同的参数:

  • 命令行
  • 来自命令行上指定路径的文件
  • 从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
$ xargs your_script.sh
-d foo
bar
baz
^D
因此,对于所有以前无疑做过这种事情的人:

  • 你打算怎么办
  • 我是不是太程序化了?用awk或类似的工具能更好地完成这项工作吗
  • 这是最好的方法吗

  • 您能想到一个标准的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
    
    而getopts f:opt
    做
    案例$opt-in
    (f) 读取文件时;做shell_函数$file;完成<$OPTARG;退出0;;
    (*):错误处理等;;
    以撒
    完成
    班次$($OPTIND-1))
    案例$#in
    (0)读取文件时;做shell_函数$file;完成;退出0;;
    (*)用于“$@”中的文件;做shell_函数$file;完成;退出0;;
    以撒
    

    不难看出这方面的变化。它还相当紧凑。

    您能想到一个标准的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
    
    而getopts f:opt
    做
    案例$opt-in
    (f) 读取文件时;做shell_函数$file;完成<$OPTARG;退出0;;
    (*):错误处理等;;
    以撒
    完成
    班次$($OPTIND-1))
    案例$#in
    (0)读取文件时;做shell_函数$file;完成;退出0;;
    (*)用于“$@”中的文件;做shell_函数$file;完成;退出0;;
    以撒
    

    不难看出这方面的变化。它还相当紧凑。

    不确定我是否有点偏离目标,但听起来你好像在试图重新发明xargs

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

    $ your_script.sh -d foo bar baz
    
    您可以按如下方式从stdin获取参数:

    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
    
    $ xargs your_script.sh
    -d foo
    bar
    baz
    ^D
    
    我们的档案

    $ cat config_file | xargs your_script.sh
    
    (假设config_文件包含以下内容)

    或来自多个配置文件

    $ cat config_file1 config_file2 | xargs your_script.sh
    

    我不确定我是否有点偏离目标,但听起来你好像在试图重新发明xargs

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

    $ your_script.sh -d foo bar baz
    
    您可以按如下方式从stdin获取参数:

    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
    
    $ xargs your_script.sh
    -d foo
    bar
    baz
    ^D
    
    我们的档案

    $ cat config_file | xargs your_script.sh
    
    (假设config_文件包含以下内容)

    或来自多个配置文件

    $ cat config_file1 config_file2 | xargs your_script.sh
    

    这听起来像是应该怎么做的,考虑到这些情况,设计的脚本可以很好地工作。谢谢。这听起来像是应该怎么做的,考虑到这些情况,设计的脚本可以很好地工作。谢谢。希望我能接受两个答案+1,非常感谢这个例子-非常有趣。希望我能接受两个答案+1,非常感谢这个例子-非常有趣。