web-dev-qa-db-ja.com

bashで文字列内の単語のインデックスを見つける方法は?

Bashスクリプトでは、

1つ以上のスペースで区切られたいくつかの単語を含む文字列があります。つまり:

Name   Age Sex  ID         Address

Wordのいずれかを検索する場合、たとえばWord "Age"のインデックスを検索する場合、どうすればよいですか?

必要なWordのインデックス番号を直接返すコマンドはありますか?

ありがとう。

10
GJ.

Bashは文字列内で Word splitting を単独で実行します–実際、たいていの場合、それを回避することが問題であり、引用が非常に重要な理由です。これを活用するのは簡単です。引用符なしで文字列を配列に入れるだけです。bashはWord分割を使用して個々の要素を分離します。文字列が変数$strに格納されていると仮定すると、

ar=($str) # no quotes!

5つの要素の配列を返します。配列インデックスは、Wordインデックス(ほとんどのスクリプト言語やプログラミング言語のように0からカウントアップ)です。つまり、「年齢」は次を使用してアクセスされます。

${ar[1]}  # 0 => Name, 1 => Age, 2 => Sex, 3 => ID, 4 => Address

または、コンテンツによって要素のインデックスを検索する必要がある場合は、配列をループします。

function el_index {
    cnt=0; for el in "${ar[@]}"; do
        [[ $el == "$1" ]] && echo $cnt && break
        ((++cnt))
    done
}
el_index "Age" # => 1
12
kopischke
$ export FOO="Name   Age Sex  ID         Address"

* AgeをAgeに置き換えます。これにより、「Age」の前のものがすべて削除されます。

$ echo ${FOO/*Age/Age}
Age Sex ID Address

「年齢」より前に何でも入手

$ echo ${FOO/Age*/}
Name

その文字列の長さ( "Age"のインデックス)を取得します。

$ BEGIN=${FOO/Age*/}
$ echo ${#BEGIN}
7
4
user1034081

シェルで次のjavascript onelinerを試してください(javascript Shellを使用)。

$ js <<< "x = 'Name   Age Sex  ID         Address'; print(x.indexOf('Age'));"
7

または、ヒアドキュメントを使用して:

js <<EOF
x = 'Name   Age Sex  ID         Address';
print(x.indexOf('Age'));
EOF
0
Gilles Quenot

Coreutilsが利用可能な場合は、次の方法で実行できます。

エコー$ {str/Age //} |カット-d/-f1 | wc -w

MariusMatutiaeのリクエストごとに、この3つのステップの操作がどのように機能するかについての説明を追加します。

echo $ {str/Age //}1。一意の文字を検索する文字列を置換します(私の場合は/)

カット-d/-f12。一意の文字の後にある文字列全体を切り取ります

wc -w3。残っている単語を数えて印刷すると、インデックス番号が得られます

参考のために確認してください:

http://www.tldp.org/LDP/abs/html/parameter-substitution.html (「変数の拡張/部分文字列の置換」に移動します)
http://www.gnu.org/software/coreutils/manual/coreutils.html (「cutコマンド」と「wc呼び出し」に移動します

0
PiotrO

:ここで、インデックスによって、文字列内の文字ではなく、どのWordが(0から始まる)かを知りたいと仮定すると、みことばが始まる。他の答えは後者に対処します。

私が知っていることではありませんが、あなたはそれを作ることができます。 2つのトリック:

  1. for構成の固有の機能を使用して、引用符で囲まれていない入力を空白で分割します。
  2. 目的の列が見つからない場合に対処します。この例では、見つかったインデックスをstoutに送信し、ステータスコードに検索が成功したかどうかを示すことを選択しました。他の可能性があります。

コード:

#!/bin/bash
find_index() {
    local str=$1
    local search=$2
    let local n=0
    local retval=1 # here, 1 is failure, 0 success
    for col in $str; do # $str unquoted -> whitespace tokenization!
    if [ $col = $search ]; then
        echo $n
        retval=0
        break
    else
        ((n++))
    fi
    done
    return $retval
}

test="Name   Age Sex  ID         Address"
idx=`find_index "$test" Age`
if [ $? -ne 0 ]; then
    echo "Not found!"
else
    echo "Found: $idx"
fi
0
Owen S.

厳密にbashを使用する必要はないが、bashを使用するシステムで一般的に見られる他のプログラムを使用できる場合は、次のようなものを使用できます。

echo "Name   Age Sex ID  Addr" | python -c 'print(raw_input().index("Age"))+1'

Pythonは文字列のインデックス作成をゼロから開始するため、コマンドの最後に+1を追加しました。

0
jftuga

私はうまく機能する解決策を見つけました。

$ string = 'now is the time'
$ buf = the $ {string#* the}
$エコー$ buf
出力:時間
$ index = $(($ {#string}-$ {#buf} + 1))
$エコー$インデックス
出力:8->最初の単語「the」のインデックス

これは、Javaの関数indexOf()と同様に機能し、入力文字列の最初の出現を返します。

この解決策はここで見つかりました http://www.linuxquestions.org/questions/linux-newbie-8/bash-string-manipulation-help-670627/ (最後の投稿)。この男は私の日を救った。彼の功績です。

最初のindexofから部分文字列を作成する場合の高速化。

$ a = "some long string"
$ b = "ri"
$エコー$ {a/* $ b/$ b}
リング
$エコー$ {a/$ b */$ b}
いくつかの長い線条

https://stackoverflow.com/questions/10349102/Shell-script-substring-from-first-indexof-substring

0
Linh Lino

Bashのネイティブ正規表現を使用できます

# a function to print the index of a field and its name
printIx() { 
  for ((l=0,i=1;i<$1;i++)) ;do 
     ((l+=${#BASH_REMATCH[i]}))
  done
  printf '%3s %s\n' $l "$2"
}

#   Using a zero based index
#   "0----+----1----+----2----+----3----+----4"
str="  Name   Age Sex  ID         Address   "

if [[ $str =~ ^(\ *)(Name)(\ +)(Age)(\ +)(Sex)(\ +()ID)(\ +)(Address)\ *$ ]] ;then
  F=(Name Age Sex ID Address)
  f=(   2   4   6  8      10)  # regex back-references
  for ((g=0;g<${#f[@]};g++)) ;do
     printIx  ${f[g]} "${F[g]}"
  done 
fi

出力

  2 Name
  9 Age
 13 Sex
 20 ID
 29 Address
0
Peter.O