grepとコマンドライン引数の使用

grepとコマンドライン引数の使用

内容を含むファイルがあります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上記の方法を使用します。また、単語の分離やファイル名のグロービングを防ぐためにパターンを参照しました。grepgrep

パターンが実際に正規表現ではなく文字列である場合は、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 "$@"

関連情報