1. ホーム
  2. string

[解決済み] シェル文字列不正置換

2022-02-17 04:27:22

質問内容

シェルプログラミングの初心者です。ZIPファイルを解凍した後のディレクトリ名を取得するつもりです。そのためのprint文は

$test.sh helloworld.zip
helloworld

それでは、test.shを見てみましょう。

#! /bin/sh
length=echo `expr index "$1" .zip`
a=$1    
echo $(a:0:length}

しかし、コンパイラからBad substitutionエラーが発生しました。

私はUbuntu 10.04を使用しており、ターミナルを使用しているため、bashや他のシェルの違いがわかりません。(私はbashを使っています。)

解決方法は?

シェルが十分に新しいバージョンである場合 bash は、その パラメータ展開 という表記が有効なはずです。

他の多くのシェルでは、これは動作せず bad substitution エラーは、シェルが「あなたはパラメータ置換を要求しましたが、私には意味をなしません」と言う方法です。


また、スクリプトを考えると

#! /bin/sh
length=echo `expr index "$1" .zip`
a=$1    
echo $(a:0:length}

2行目は、変数 length という値で echo を実行することで生成されるコマンドに対して expr index "$1" .zip . には代入されません。 length . で済むはずです。

length=$(expr index "${1:?}" .zip)

ここで ${1:?} の場合、エラーが発生します。 $1 が設定されていない場合 (スクリプトが引数なしで起動された場合)。

最後の行は、こうでなければなりません。

echo ${a:0:$length}

ただし、もし $1filename.zip の出力は expr index $1 .zip は2なので、文字 i のインデックス2に出現する。 filename.zip . を使わずにファイルのベース名を取得することを意図している場合、そのファイルには .zip という拡張子を付けると、古典的な方法となります。

base=$(basename $1 .zip)

と、より現代的な方法です。

base=${1%.zip}

違いは、名前が /path/to/filename.zip の場合、古典的な出力は filename であり、現代のものは /path/to/filename . でクラシックな出力が得られます。

base=${1%.zip}
base=${base##*/}

また、クラシック版では、パスで取得します。

base=$(dirname $1)/$(basename $1 .zip)`.)

ファイル名にスペースが含まれる場合は、ダブルクォートを使うことを考える必要があります。 basenamedirname .