【问题标题】:cut -d, ignore delimiter in argumentcut -d,忽略参数中的分隔符
【发布时间】:2016-10-19 12:56:26
【问题描述】:

我编写了一个脚本,它可以获取可变数量的参数:

test.sh -i <input1> <input2> ... -o <output1> <output2> ...

我正在解析参数如下:

while [ $# -gt 1 ]; do
        TMP=$(echo "$@" | cut -d '-' -f 2)  #i <input1> <input2>
        TMP1=$(echo "$TMP" | cut -d ' ' -f 1)  #i
        CNT=$(echo "$TMP" | wc -w)  #3
        set -x
        case "$TMP1" in
            i)
                INPUTS=$(echo "$TMP" | cut -c 3-)
                shift "$CNT"
                ;;
            o)
                OUTPUTS=$(echo "$TMP" | cut -c 3-)
                shift "$CNT"
                ;;
        esac
done

这每次都有效,但名称中恰好有“-”的文件除外。

例子:

./test.sh -i file1.txt file-2.txt -o out1.txt out-2.txt

我是否可以强制cut 忽略文件名中出现的分隔符?

【问题讨论】:

  • 我不知道 getopts 。我将不得不检查它是否在我正在使用的机器上可用
  • 为什么不从 $# 倒计时并在每个 arg 上运行 [ -f "$arg" ],然后再切割“-”分隔的参数,而不是在 $@ 上运行 cut 过滤器,您可以在"$input" 上运行它 - $input 是您从所有“非文件”参数构造的新数组变量。如果以后没有解决这个问题,我会发布一个例子
  • getopts 不适用于带有多个参数的选项。

标签: bash parsing unix delimiter


【解决方案1】:

您不需要所有这些字符串操作;每个参数已经是一个单独的词。

while (( $# > 0 )); do
  case $1 in
    -i) shift
        while [[ $# -gt 0 && $1 != -* ]]; do
            inputs+=( "$1" )
            shift
        done
        ;;
    -o) shift
        while [[ $# -gt 0 && $1 != -* ]]; do
            outputs+=( "$1" )
            shift
        done
        ;;
    *) echo "Unrecognized option $1"
       exit 1
       ;;
  esac
done

这可以稍微重构以避免重复检查参数用完。

for arg in "$@"; do
    case $1 in
      -i) mode=input; continue ;;
      -o) mode=output; continue ;;
    esac
    case $mode in
      input) input+=("$arg") ;;
      output) output+=("$arg") ;;
      *) echo "Unknown mode: $mode"
         exit 1
         ;;
    esac
done

【讨论】:

  • 您的解决方案简单易懂。我的事情好像有点复杂。
【解决方案2】:

这是一种可能使某人受益的替代方法。

事实上,参数解析始终是一种权衡,因此根据应用程序对其进行定制是有好处的。这是一个非常通用的解决方案,它允许在参数中进行一些错误检查和混乱。

这很简单,但是我添加了一些示例输出和 cmets,并且为了可读性和兼容性,避免使用复杂的方法来保存一两行(尤其是在 if 语句上)。

示例用法:

bash #> touch file-1 file3 file4 file-8 file7
bash #> argparse -i file-1 file3 file4 -c -k --q --j -r -t -o file-8 file7

输出

输入文件:file-1 file3 file4 输出文件:file-8 file7 参数是:c k q j r t 为参数“c”执行操作 为参数“k”执行操作 为参数“j”执行操作

脚本:

#!/bin/bash
#argparse

#Assign arrays

until [[ $# < 1 ]]; do
#ignore args "-i" and "-o", and tell the script to check for files following
    if [ "$1" == "-i" ] ; then unset output ; input=1 ; shift 
    elif [ "$1" == "-o" ] ; then unset input ; output=1 ; shift 
    fi
#Add input and output files to respective arrays
    if [ -f "$1" ] ; then 
        if [[ $input == 1 ]]; then 
            infiles+=($1)
        elif [[ $output == 1 ]]; then 
            outfiles+=($1)
        fi
    else
#Add args to array
        arg="$(echo "$1" | sed 's/-//g')"
        args+=($arg)
    fi
    shift
done

#Some debug feedback
echo -e "Input files: ${infiles[@]}\nOutput files: ${outfiles[@]}\nArgs are: ${args[@]}\n"

#Simulate actually "doing" something with the args
for arg in "${args[@]}" ; do 
    case $arg in
        "c") echo "Doing action for argument \"c\"" ;;
        "k") echo "Doing action for argument \"k\"" ;;
        "j") echo "Doing action for argument \"j\"" ;;
        *) ;;
    esac
done

更新/编辑:我刚刚意识到,除了-i-o 之外,OP 对解析实际 参数没有任何要求。好吧,无论如何,这在某些时候可能仍然对某人派上用场。

【讨论】:

    猜你喜欢
    • 2020-12-30
    • 2018-03-25
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多