内容を含むファイルがありますf1
。
james john joe
marie james
joe
don marie
grep
シェルスクリプトで以下を使用して、s1.sh
各行のコマンドラインパラメータの発生を出力したいと思います。
#!/bin/bash
for ((i = $# ; i > 0 ; i-- ))
do
grep -c $i f1
done
次のように実行するとします。
s1.sh james joe
スクリプトが変数をi
位置パラメータとして解釈するにはどうすればよいですか?
答え1
スクリプトの引数を一度に1つずつ使用する場合は、grep
算術ループを実行する必要はありませんfor
。
#!/bin/sh
for pattern do
grep -c -e "$pattern" f1
done
このfor
ループは、スクリプトのパラメータである位置パラメータを繰り返します。各反復で、この値は$pattern
次のコマンドライン引数になります。
また、ダッシュで始まるパターンがオプションとして誤って解釈されるのを防ぐために、-e
上記の方法を使用します。また、単語の分離やファイル名のグロービングを防ぐためにパターンを参照しました。grep
grep
パターンが実際に正規表現ではなく文字列である場合は、withのgrep
使用を検討してください-F
。
位置引数のリストを使用でき"$@"
、上記のループはこれを暗黙的に使用します。繰り返すには、"$@"
次のようにします。
for pattern in "$@"; do
...
done
引用は必須です。それ以外の場合は、スクリプト引数に対してトークン化とファイル名の一致を実行します。
この答えにはシェルコードは必要ないので、-lineを使用していますbash
。/bin/sh
#!
答え2
スクリプトが変数を
i
位置パラメータとして解釈するにはどうすればよいですか?
おそらく、Bashで変数でインデックス付けされた位置引数を取得する最も簡単な方法は、配列スライス表記を位置引数に$@
.extendedに適用することです。"${@:n:k}"
N到着n+k-1から まで"${array[@]:n:k}"
配列要素に拡張するのと同じです。"${array[n]}"
"${array[n+k-1]}"
NそしてK評価にはシェル算術を使用しているため、たとえばpositionに引数が1つしか与えられない場合は、"${@:a+b-1:1}"
これを実行できます。"${@:i:1}"
i
あるいは、間接拡張${!var}
も位置引数を処理するため、たとえばwithがi=2
提供さ"${!i}"
れます"$2"
。まあ、これも上記より短いです。一方、namerefsはいいえ位置パラメータを使用するとdeclare -n ref=2
エラーが発生します...
たとえば、参照してください。Bashはポインタの使用をサポートしていますか?
別のアプローチは、位置引数のリストを名前付き配列にコピーし、通常の方法でインデックスを作成することです。args=("$@")
コピーして使用してください"${args[i]}"
。ここでも、インデックスは算術拡張です。
もちろん、位置パラメータにアクセスしたい場合増加通常どおり、順序には実際に示された逆順は必要なく、Kusalandaの答えに示されているようにfor x in "$@"; do ...
orを使用するだけです。for x do ...
ただし、同じループ構成を使用して位置引数のリストを最初に反転することもできます。たとえばdd cc bb aa
、名前指定子、逆参照、または配列がない通常のshでも、次のように印刷されます。
set -- aa bb cc dd
first=1
for x in "$@"; do
# on first iteration, clear the list
[ "$first" = 1 ] && set --
first=
set -- "$x" "$@"
done
echo "$@"