将脚本作为参数Bash传递

时间:2017-10-18 18:15:20

标签: bash

这个脚本不完整,因为我想稍后进行错误测试,但想法是ARG是一个脚本而ARG2是一个目录,而ARG应该标记ARG2中的所有文件。我怎么能这样做,以至于bash知道第一个参数必须是一个脚本而参数2是一个目录?

ARG=$1
ARG2=$2
CHECK=0
aCount=0
bCount=0
cCount=0
dCount=0
fCount=0

if [ $CHECK -e 0 ]; then
    for files in $ARG2; do
        if [ sh $1 $2 -eq A]; then
            aCount=$((aCount+1))
        elif [ sh $1 $2 -eq B]; 
            bCount=$((bCount+1))
        elif [ sh $1 $2 -eq C]; 
            cCount=$((cCount+1))
        elif [ sh $1 $2 -eq D ];
            dCount=$((dCount+1))
        else;
            fCount=$((fCount+1))
        fi
    done
fi

echo A: $aCount
echo B: $bCount       
echo C: $cCount          
echo D: $dCount
echo F: $fCount

2 个答案:

答案 0 :(得分:4)

通过 shellcheck.net 运行脚本可能会遇到各种错误。

<强>更正:

  • 要遍历目录中的文件,请写for file in dir/*而不是for file in dir。后者只是循环一次,$file设置为字符串"dir",而不是遍历目录dir/的内容。

  • [ sh $1 $2 -eq A]是一堆混乱的shell结构。您想要捕获脚本的输出,因此需要$(...)。您正在进行字符串检查,因此您应该使用==而不是-eq。纠正两个收益率:

    [ $(sh $1 $2) == A ]
    
  • 我猜$2应该是$files。循环变量,是吗?

    [ $(sh $1 $files) == A ]
    
  • 还有其他杂项错误,例如遗失then并且]之前没有空格。

<强>改进:

  • 您应该正确引用所有内容,以防止无意中的单词拆分和全局扩展。

    [ "$(sh "$1" "$files")" == A ]
    
  • 让我们用$1替换$script,用$files替换$file

    [ "$(sh "$script" "$file")" == A ]
    
  • 如果脚本顶部有一个像#!/bin/bash那样合适的shebang行,那么就不需要显式调用sh

    [ "$("$script" "$file")" == A ]
    
  • 这一切都很棒。现在你有这样的事情:

    if [ "$("$script" "$file")" == A ]; then
        aCount=$((aCount+1))
    elif [ "$("$script" "$file")" == B ]; then
        bCount=$((bCount+1))
    elif [ "$("$script" "$file")" == C ]; then
        cCount=$((cCount+1))
    elif [ "$("$script" "$file")" == D ]; then
        dCount=$((dCount+1))
    else
        fCount=$((fCount+1))
    fi
    

    非常重复,不是吗?我们来试试case语句。

    case "$("$script" "$file")" in
        A) aCount=$((aCount+1));;
        B) bCount=$((bCount+1));;
        C) cCount=$((cCount+1));;
        D) dCount=$((dCount+1));;
        *) fCount=$((fCount+1));;
    esac
    
  • 那个案例陈述仍然很复杂。让我们分解它以便更容易解析。

    grade=$("$script" "$file")
    
    case $grade in
        ...
    esac
    
  • 变量名应该是小写的。大写的名称是为shell保留的,所以最好不要使用它们。将COUNT更改为count

  • 我们分别将ARGARG2重命名为scriptdir。有意义的名字使一切更容易阅读。

  • var=$((var+1))可简化为((var += 1))((var++))

最终结果:

script=$1
dir=$2

check=0
aCount=0
bCount=0
cCount=0
dCount=0
fCount=0

if ((check == 0)); then
    for file in "$dir"/*; do
        grade=$("$script" "$file")

        case $grade in
            A) ((aCount++));;
            B) ((bCount++));;
            C) ((cCount++));;
            D) ((dCount++));;
            *) ((fCount++));;
        esac
    done
fi

echo "A: $aCount"
echo "B: $bCount"
echo "C: $cCount"
echo "D: $dCount"
echo "F: $fCount"

答案 1 :(得分:2)

@ John Kugelman上面做了伟大的工作。换句话说 -

declare -A count                   # count is an array
for file in "$dir"/*               # skipping assignments, and $check
do grade=$("$script" "$file")      # grab the output as $grade
   case $grade in                  # look up its value
   [A-D]) (( count[$grade]++ ));;  # use as-is for a-d
       *) (( count['F']++    ));;  # throw everything else in f
   esac
done

for g in A B C D F                 # then for a-f (known values)
do echo "$g: "${count[$g]}         # pull the counts
done