私は次のスクリプトを見つけました。
#! /bin/bash
if (( $# < 3 )); then
echo "$0 old_string new_string file [file...]"
exit 0
else
ostr="$1"; shift
nstr="$1"; shift
fi
echo "Replacing \"$ostr\" with \"$nstr\""
for file in $@; do
if [ -f $file ]; then
echo "Working with: $file"
eval "sed 's/"$ostr"/"$nstr"/g' $file" > $file.tmp
mv $file.tmp $file
fi
done
彼らが使う線の意味は何ですかshift
?スクリプトは少なくともパラメータで使用する必要があると思いますが…?
答え1
shift
bash
パラメータリストの先頭からパラメータを削除する組み込み関数。スクリプトに提供された3つの引数が$1
、で$2
使用できると仮定すると、$3
呼び出しはnewをshift
生成します。 Aは2だけ新しいoldに変換されます。詳しくはこちらをご覧ください。$2
$1
shift 2
$1
$3
答え2
Goldilocksのコメントとヒューマンリファレンスで説明されているように、 位置shift
パラメータ(など)を再割り当てして、背面の以前の値を取得します。* 以前の値は破棄されます。 (変更されていません。)これを行ういくつかの理由は次のとおりです。$1
$2
$1
$2
$2
$3
$1
$0
- 10番目のパラメータ(存在する場合)に簡単にアクセスできます。動作しません。 aに関連付けられている
$10
と解釈されます(したがって、同様の結果が生成される可能性があります)。 a次の10番目のパラメータはになります。 (ただし、ほとんどの最新のシェルでは使用できます。)$1
0
Hello0
shift
$9
${10}
- 〜のようにBash初心者ガイドパラメータを繰り返すために使用できることが証明されています。 IMNSHO、これは素朴です
for
。 - サンプルスクリプトと同様に、いくつかのパラメータを除くすべてのパラメータを同じ方法で簡単に処理できます。たとえば、スクリプトでは、およびは
$1
テキスト$2
文字列、$3
他のすべてのパラメータはファイル名です。
結果は次のとおりです。スクリプトが呼び出され、Patryk_script
呼び出されるとします。
Patryk_script USSR Russia Treaty1 Atlas2 Pravda3
スクリプトは見る
$1 = USSR
$2 = Russia
$3 = Treaty1
$4 = Atlas2
$5 = Pravda3
このステートメントはostr="$1"
変数ostr
をに設定しますUSSR
。最初のshift
ステートメントは、位置パラメーターを次のように変更します。
$1 = Russia
$2 = Treaty1
$3 = Atlas2
$4 = Pravda3
このステートメントはnstr="$1"
変数nstr
をに設定しますRussia
。 2番目のshift
ステートメントは、位置パラメータを次のように変更します。
$1 = Treaty1
$2 = Atlas2
$3 = Pravda3
その後、ループはファイルの()をfor
()に変更します。USSR
$ostr
Russia
$nstr
Treaty1
Atlas2
Pravda3
スクリプトにはいくつかの問題があります。
$@ のファイルについては、次のようにします。
スクリプトが次のように呼び出される場合
Patryk_script ソビエトロシア条約1「World Atlas 2」 Pravda 3
それを見る
1 USD = ソ連 2ドル=ロシア $3 = 条約 1 $ 4 =ワールドアトラス2 $5 = プラウダ 3
しかし、
$@
空白はWorld Atlas2
引用されていないので引用されず、ループfor
は、、、Treaty1
および4つのファイルがあると思います。これはおそらくWorld
Atlas2
Pravda3
「$@」にあるファイルの場合は、次のようにします。
(引数に特殊文字を引用してください)または単に
ファイルの場合
(より長いバージョンと同じ)
eval "sed's/"$ostr"/"$nstr"/g' $file"
これをに設定する必要はなく、
eval
未確認のユーザー入力をに渡すのはeval
危険です。たとえば、スクリプトが次のように呼び出されるとPatryk_script "'; rm *;'" ロシア条約 1 Atlas2 Pravda3
それが行われます
rm *
!たとえば、sudo
Webインターフェイスを介してスクリプトを実行または呼び出すことができる場合、スクリプトを呼び出すユーザーよりも高い権限で実行できる場合、これは大きな問題です。ディレクトリで直接使用する場合は、それほど重要ではないかもしれません。ただし、次のように変更されることがあります。sed "s/$ostr/$nstr/g" "$file"
それでもやや危険がありますが、それほど危険ではありません。
if [ -f $file ]
、> $file.tmp
およびは、スペース(またはその他の興味深い文字)を含めることができるファイル名を処理するためにそれぞれ、およびでなければmv $file.tmp $file
なりません。 (このコマンドはスペースを含むファイル名も削除します。)if [ -f "$file" ]
> "$file.tmp"
mv "$file.tmp" "$file"
eval "sed …
* shift
オプションの引数を取ります。移動する引数の数を指定する正の整数。デフォルト値は1(1
)です。たとえば、になる原因shift 4
などがあります。 (例で参考にしてください。$5
$1
$6
$2
Bash初心者ガイドそれは間違っています。 )スクリプトは次のように変更できます。
ostr="$1"
nstr="$2"
shift 2
これがより明確であると見ることができます。
アメリカ/警告する:
Windowsのコマンドプロンプト(バッチファイル)言語は、デフォルトでSHIFT
Unixシェルのコマンドと同じ操作を実行するコマンドもサポートしていますshift
が、人々が混乱しないように隠す重要な違いが1つあります。
- このコマンド
SHIFT 4
はエラーであり、「SHIFTコマンドの無効な引数」エラーメッセージが生成されます。SHIFT /n
、どこn
0 ~ 8 の整数で、有効ですが移動されません。n
移流。一度変身して、から始まるこれN 番目のパラメータです。したがってSHIFT /4
結果%5
(5番目のパラメータ)はとなり%4,
%6
、%5
このようにしてパラメータ0~3だけ残ります。
答え3
最も簡単な説明はこれです。次のコマンドを検討してください。
/bin/command.sh SET location Cebu
/bin/command.sh SET location Cebu, Philippines 6014
ヘルプがないと、shift
値がランダムに長くなる可能性があるため、場所の値全体を抽出することはできません。 2回移動すると、argsと次のようにSET
削除location
されます。
x="$@"
echo "location = $x"
$@
そのものを長く見つめてください。これはx
、スペースとコンマが含まれていても、場所全体を変数に保存できることを意味します。つまり、shift
変数に残っている値を呼び出して検索します$@
。
修正する
以下に、概念と使用法を示す非常に短いコードスニペットを追加しました。shift
これがなければ、フィールドを正しく抽出するのは非常に難しいでしょう。
#!/bin/sh
#
[ $# -eq 0 ] && return 0
a=$1
shift
b=$@
echo $a
[ -n "$b" ] && echo $b
説明する:以後shift
、可変第二スペースなどに関係なく、配信された残りのコンテンツを含める必要があります。これは[ -n "$b" ] && echo $b
保護装置です。私たちは印刷するだけです。第二内容がある場合です。
答え4
shift
コマンドライン引数を呼び出すたびに、要素が表示されるFIFOキューとして扱われます。
array = [a, b, c]
shift equivalent to
array.popleft
[b, c]
$1, $2,$3 can be interpreted as index of the array.
$# is the length of array