Obtém a próxima palavra de uma substring em uma string

2

Eu preciso pegar a próxima palavra de uma palavra em uma string. Eu tentei escrever um script, mas não está funcionando. E é bom se você me sugerir outras alternativas para conseguir isso.

Script:

#!/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

Eu quero pegar a palavra depois de "-where". Mas acima script não está funcionando. Eu não entendi onde estou perdendo. Obrigado.

    
por gangadhars 28.08.2015 / 14:20

5 respostas

7

Sugiro contratar grep para este trabalho:

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

Explicação:

  • -P : expressão regular compatível com perl
  • -o : mostra apenas partes correspondentes
  • \K : largue tudo antes desse ponto
  • \w* : constituinte da palavra match (sinônimo para [_[:alnum:]] )

Para adicionar " à lista de caracteres correspondentes:

$ grep -Po -- '-eats \K[_\"[:alnum:]]*' <<< $OPTS
Brains"
    
por 28.08.2015 / 14:29
7

POSIXly:

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

Ou para permitir qualquer número de espaços em branco entre palavras:

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

Ou você poderia fazer:

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#-}=\" # assigns name=$2 or where=$2...
       shift 2;;
    (*) shift
  esac
done
printf '%s\n' "$name eats $eats in $where"

Observe que, em um deles, os espaços em branco são limitados a espaço, tabulação (e nova linha) e não aos outros caracteres que podem ser considerados como [:blank:] em sua localidade.

    
por 28.08.2015 / 14:35
4

Uma pequena edição no seu script:

#!/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
    
por 28.08.2015 / 14:32
0

Outro POSIX 1:

printf %s\n "$opts" | tr -cs '[[:alnum:]-]' '[\n*]' | sed -n '/-where/{
  n
  p
}'
Asia

(Observe que o GNU tr não funciona com caracteres de vários bytes)

    
por 28.08.2015 / 18:25
0

Usando 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"

Saída

Asia

usando tr e sed

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

usando tr e awk

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

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