文字列からサブ文字列の次の単語を取得します。

文字列からサブ文字列の次の単語を取得します。

文字列から単語の次の単語を取得する必要があります。スクリプトを作成しようとしても機能しません。これを達成するための他の代替案を提案してください。

スクリプト:

#!/bin/bash
opts="OPTS=\"-name user -age 20 -where Asia -eats Brains\""
echo $opts
ok="0"
for word in $opts; do
  if [ "$word" = "-where" ] ; then
    if [ "$ok" = "1" ] ; then
      echo $word
      break
    fi
    ok="1"
  fi
done

「-where」の後に単語を取得したい。しかし、上記のスクリプトは機能しません。私は何を見逃しているのか分かりません。ありがとうございます。

答え1

私はgrepこの役職に採用することをお勧めします:

$ OPTS="\"-name user -age 20 -where Asia -eats Brains\""
$ grep -Po -- '-where \K\w*' <<< "$OPTS"
Asia

説明する:

  • -P: Perl 互換正規表現
  • -o:一致する部分のみを表示
  • \K:その時点より前のすべての項目を破棄します。
  • \w*:一致単語コンポーネント(の同義語[_[:alnum:]]

"一致する文字リストに追加するには:

$ grep -Po -- '-eats \K[_\"[:alnum:]]*' <<< $OPTS
Brains"

答え2

POSIX的に:

after_first_where=${opts#*-where }
word_after_where=${after_first_where%% *}

または、単語間のスペースを許可します。

after_first_where=${opts#*-where}
word_after_where=${after_first_where#"${after_first_where%%[![:blank:]]*}"}
word_after_where=${word_after_where%%[[:blank:]]*}

またはこれを行うこともできます:

unset -v IFS; set -f # split on blanks, no glob
set -- $opts # splits $opts into $1, $2, $3...
while [ "$#" -ge 2 ]; do
  case $1 in
    (-age|-name|-where|-eats)
       eval "${1#-}=\$2" # assigns name=$2 or where=$2...
       shift 2;;
    (*) shift
  esac
done
printf '%s\n' "$name eats $eats in $where"

スペースはスペース、タブ(および改行)に制限され、地域[:blank:]で考慮される可能性がある他の文字は該当しません。

答え3

スクリプトを一部編集します。

#!/bin/bash
opts="OPTS=\"-name user -age 20 -where Asia -eats Brains\""
echo $opts
ok="0"
for word in $opts; do
  if [ "$ok" = "1" ] ; then
    echo $word
    break
  fi
  if [ "$word" = "-where" ] ; then
    ok="1"
  fi
done

答え4

使用awk

opts="OPTS=\"-name user -age 20 -where Asia -eats Brains\""
awk '{for(i=1;i<=NF;i++) {if($i~"-where") {print $(i+1)}}}' <<< "$opts"

出力

Asia

使用trsed

tr ' ' '\n' <<< "$opts" | sed -n '/-where/{n;p}'
Asia

使用trawk

tr ' ' '\n' <<< "$opts" | awk '/-where/{getline;print;}'
Asia

tr ' ' '\n' <<< "$opts" | awk '/-where/{x=NR+1;next}(NR<=x){print}'
Asia

関連情報