bashスクリプトでは、
1つ以上のスペースで区切られた複数の単語を含む文字列があります。つまり:
Name Age Sex ID Address
「Age」という単語のインデックスを検索するなど、単語を検索したい場合はどうすればよいですか?
必要な単語のインデックス番号を直接返すコマンドはありますか?
ありがとう。
bashスクリプトでは、
1つ以上のスペースで区切られた複数の単語を含む文字列があります。つまり:
Name Age Sex ID Address
「Age」という単語のインデックスを検索するなど、単語を検索したい場合はどうすればよいですか?
必要な単語のインデックス番号を直接返すコマンドはありますか?
ありがとう。
回答:
Bashは文字列の単語分割をそれ自体で実行します。実際、たいていの場合、それを回避することが問題であり、引用が非常に重要な理由です。これを活用するのは簡単です。引用符を付けずに文字列を配列に入れるだけです。bashは単語分割を使用して個々の要素を分離します。文字列が変数$str
に格納されていると仮定すると、
ar=($str) # no quotes!
5つの要素の配列を返します。配列インデックスは、単語インデックス(ほとんどのスクリプト言語やプログラミング言語のように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
$ 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
export L='debug info warn error'; export GTE='warn'; echo ${L/*${GTE}/${GTE}}
「警告エラー」を出力します
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から始まる)どの単語であるかを知りたいと想定していることを前提としています。他の答えは後者に対処します。
私が知っていることではありませんが、あなたはそれを作ることができます。2つのトリック:
コード:
#!/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
私はうまく機能する解決策を見つけました。
$ string = 'now is the time'
$ buf = the $ {string#* the}
$ echo $ buf
output:the time
$ index = $(($ {#string}-$ {#buf} + 1))
$ echo $ index
output:8->最初の単語「the」のインデックス
これは、入力文字列の最初のオカレンスを返すJavaの関数indexOf()と同様に機能します。
このソリューションは、http://www.linuxquestions.org/questions/linux-newbie-8/bash-string-manipulation-help-670627/(最後の投稿)で見つかりました。この男は私の日を救った。彼の功績です。
最初のindexofから部分文字列を作成する場合は、より高速な方法。
$ a = "some long string"
$ b = "ri"
$ echo $ {a / * $ b / $ b}
ring
$ echo $ {a / $ b * / $ b}
some long stri
/programming/10349102/shell-script-substring-from-first-indexof-substring
coreutilsが利用可能な場合は、次の方法で実行できます。
エコー$ {str / Age //} | カット-d / -f1 | wc -w
MariusMatutiaeのリクエストごとに、この3つのステップの操作がどのように機能するかの説明を追加します。
echo $ {str / Age //} 1.一意の文字を検索する文字列を置換します(私の場合は/)
cut -d / -f1 2.一意の文字の後の文字列全体を切り取ります
wc -w 3.残っている単語を数えて出力すると、インデックス番号が表示されます。
参考のために確認してください:
http://www.tldp.org/LDP/abs/html/parameter-substitution.html(「変数拡張/サブストリング置換」に移動)
http://www.gnu.org/software/coreutils/manual/coreutils .html(「カットコマンド」と「WC呼び出し」に移動します
純粋なbash配列と部分文字列置換を使用した、以前に与えられた2つの答えの組み合わせ。
アイデアは、必要な単語の前にすべての単語の文字列を取得し、それを配列にして、その部分文字列の単語数を数えることです。
$ haystack="Name Age Sex ID Address"
$ words_before=( ${haystack%Age*} ) # truncate string, make array
$ echo ${#words_before[*]} # count words in array
1
もちろん、Ageを別の変数needle
に格納してから使用できます${haystack%$needle*}
。検索する単語が別の単語のサブセットである場合、問題が発生する可能性があります。その場合、コピッシュケの回答は引き続き機能します。