文字列内の部分文字列の位置を見つける

文字列内の部分文字列の位置を見つける

「schemas.txt」ファイルで、ユーザーが入力した3番目のフィールドの場所を抽出したいと思います。

schemas="schemas.txt"
for i in ${schemas[@]};
do
    awk '{for(i=1;i<=NF;i++)if($i=="$3")print i}'
done 

無限ループに閉じ込められた理由のアイデアはありますか?

編集:以下に例を追加しました。

Schemas.txtの2行目は「キャラクターキー、体重、年齢、レース、職業」です。

ユーザーが3番目のパラメータとして「age」と入力したとします。文字列の4番目の単語なので、行を解析して「4」を返したいと思います。

ベストアンサー1

あなたの意図を理解するならば、シェルループは必要ないと思います。代わりに、コマンドラインから読み取るファイル名をawkに指定してください。 find-vコマンドラインでawk変数を設定するキーワードを渡すことができます。

したがって、「age」を含む各行に発生するフィールド番号が印刷されます。

$ cat schemas.txt
People height weight age race occupation
age is first on this line
$ keyword=age
$ awk -vk="$keyword" '{ for (i = 1 ; i <= NF ; i++) if($i == k) print i }' schemas.txt 
4
1

もちろん、固定キーワードはを使用できる例に過ぎず、追加のawk -vk="$3"変数はスキップできます。

通常、行番号を印刷することも便利でそうすることができますprint NR, i


ここでは、

schemas="schemas.txt"
for i in ${schemas[@]};
do
    awk '{for(i=1;i<=NF;i++)if($i=="$3")print i}'
done 

schemasのみを含むので、schemas.txtループi内でシェル変数が設定されます。しかし、ループでは使用されないため、ループは実際には多くのことを行いません。 awkスクリプトはシェルにi依存しませんi

awk基本的には標準入力から読んでいるのでここで停止しているようです。また、"$3"一重引用符内のシェルでは拡張されないため、awkは$3

複数のファイルの場合、ループがより適しています。

files=(file1.txt file2.txt)
for file in "${files[@]}"; do
    awk '{...}' "$file"
done

しかし、そのような場合でも、すべてのファイルを一度にawkに渡すことができます。

awk '{...}' "${files[@]}"

おすすめ記事