Ubuntuでこのwhile-caseが機能しないのはなぜですか?

Ubuntuでこのwhile-caseが機能しないのはなぜですか?

BSDから完全なLinuxに移行しています。 Ubuntu 16.04のスクリプト

#!/bin/sh
while (( "$#" )); do
   case "$1" in
    -i | --ignore-case)
        [ $# -ne 2 ] && echo "2 arguments i needed" && exit 1
        case_option=-i
        ;;
    -*)
        echo "Error: Unknown option: $1" >&2
        exit 1
        ;;
     *) # No more options
        break
        ;;
   esac

   shift
done

# -o, if not, then ...
find $HOME ! -readable -prune -o \
    -type f -name "*.tex" -exec grep -l $case_option "$1" {} + | vim -R -

エラーはループにあります。

  • sh ./script masi期待した出力と同じ出力を返します。
  • ランニングsh ./script -i masi。出力:空のファイル。期待される出力:結果のリスト。スタウトは./script: 2: ./script: 2: not found Vim: Reading from stdin...

考えられるエラー

  • while (( "$#" ))
  • ...

何らかの理由でこのオプションはまったく使用できません。

getoptsに行きたい動機 - Terdonの答え

地図時間そして答えここ

case_option=""

while getopts "i:" opt; do
    case $opt in
        i | ignore_case) 
            [[ $# -ne 2 ] && echo "2 arguments i needed" && exit 1
            case_option=-i
            ;;
        -*)
            echo "Error: Unknown option: $1" >&2
            exit 1
            ;;
        *) # No more options 
           break
           ;;
    esac
done

find $HOME ! -readable -prune -o \
   -type f -name "*.tex" -exec grep -l $case_option "$1" {} + | vim -R -

どこ

  • ./script masiまたは電話で./script -i masi

whileケースを繰り返す方法は?

答え1

dashshorの代わりにandを使用して実行するため失敗しますbash。 Ubuntuは、最小限のPOSIX互換シェルである/bin/shシンボリックリンクです。/bin/dash最も簡単な解決策はスクリプトを実行することですが、期待bashどおりに機能しません。

bash ./script masi

また、シェバンラインがあることに注意してください。

#!/bin/sh

つまり、実行する必要はなく、sh ./script実行するだけです./script。代わりに、bashを指すようにshebang行を変更してくださいsh

#/bin/bash

sh(Ubuntuで)頑固な場合は、ループを次のように変更するdash必要があります。while

while [ "$#" -gt 0 ]; do

または、次のことを見たいと思うかもしれません。getopts

答え2

getoptsオプションパラメータを処理すると、スクリプトが実行する操作には影響しません。

以下は小さな作業フレームワークです。

case_option="" 

while getopts "i:" opt; do 
    case $opt in 
        'i') 
                I_ARG=$OPTARG 
                ;; 
        '?') 
                exit 1 
                ;;  
    esac 
done
shift $(($OPTIND - 1)) 
echo $@ 

答え3

以下は、オプション処理の2つの例です。まず組み込みシェルを使用しgetoptsてからgetoptfromを使用しますutil-linux

getoptsオプションはサポートされておらず、--long短いオプションのみがサポートされています。

getoptどちらもサポートされています。使用するには、getoptパッケージのバージョンを使用してくださいutil-linux欲しくない他のバージョンのgetoptを使用すると、破損して使用するのは安全ではなく、機能する唯一のバージョンutil-linuxです。getopt

幸いなことに、Linuxでは、util-linux破損したバージョンを特にインストールしない限り、このバージョンのみを使用できます。

getopts移植性が高く(ほとんどまたはすべてのBourne-Shellサブアイテムで動作します)、自動的に多くの操作を実行します(設定が少なく、オプションにパラメータがあるかどうかに応じてすべてのオプションを実行またはターゲットにするshift必要shift 2があります)なし)パフォーマンスは低下します。 (長いオプションはサポートしていません)

-iとにかく()オプションを処理するだけでなく、()オプションと引数()が必要なオプションの例も--ignore-case追加しました。実行方法を示す以外に、他の目的はありません。-h--help-x--example

の場合、getoptsコードは次のようになります。

#! /bin/bash

usage() {
# a function that prints an optional error message and some help.
# and then exits with exit code 1
[ -n "$*" ] && printf "%s\n" "$*" > /dev/stderr

cat <<__EOF__
Usage:
      $0 [-h] [ -i ] [ -x example_data ]

-i    Ignore case
-x    The example option, requires an argument.
-h     This help message.

Detailed help message here
__EOF__

exit 1
}

case_option=''
case_example=''

while getopts "hix:" opt; do
    case "$opt" in
        h) usage ;;
        i) case_option='-i' ;;
        x) case_example="$OPTARG" ;;
        *) usage ;;
    esac
done
shift $((OPTIND-1))

find "$HOME" ! -readable -prune -o -type f -name "*.tex" \
    -exec grep -l ${case_option:+"$case_option"} "$1" {} + |
    vim -R -

からgetoptutil-linux

#! /bin/bash

usage() {
# a function that prints an optional error message and some help.
# and then exits with exit code 1
[ -n "$*" ] && printf "%s\n" "$*" > /dev/stderr

cat <<__EOF__
Usage:
      $0 [ -h ] [ -i ] [ -x example_data ]
      $0 [ --help ] [ --ignore-case ] [ --example example_data ]

-i, --ignore-case    Ignore case
-x, --example        The example option, requires an argument.
-h, --help           This help message

Detailed help message here
__EOF__

exit 1
}

case_option=''
case_example=''

# getopt is only safe if GETOPT_COMPATIBLE is not set.
unset GETOPT_COMPATIBLE

# POSIXLY_CORRECT disables getopt parameter shuffling, so nuke it.
# parameter shuffling moves all non-option args to the end, after
# all the option args.  e.g. args like "-x -y file1 file2 file3 -o optval"
# become "-x -y -o optval -- file1 file2 file3"
unset POSIXLY_CORRECT

OPTS_SHORT='hix:'
OPTS_LONG='help,ignore-case,example:'
# check options and shuffle them
TEMP=$(getopt -o "$OPTS_SHORT" --long "$OPTS_LONG" -n "$0" -- "$@")

if [ $? != 0 ] ; then usage ; fi

# assign the re-ordered options & args to this shell instance
eval set -- "$TEMP"

while true ; do
  case "$1" in
    -i|--ign*) case_option='-i' ; shift ;;
    -x|--exa*) case_example="$2" ; shift 2 ;;

    -h|--hel*) usage ;;

    --) shift ; break ;;
     *) usage ;;
  esac
done

find "$HOME" ! -readable -prune -o -type f -name "*.tex" \
    -exec grep -l ${case_option:+"$case_option"} "$1" {} + |
    vim -R -

関連情報