Como encontrar o índice de uma palavra em uma string no bash?

8

No script bash,

Eu tenho uma string que contém várias palavras separadas por um ou mais espaços. ou seja:

Name   Age Sex  ID         Address

Se eu quiser encontrar alguma palavra, por exemplo, quero encontrar o índice da palavra "Idade", como posso fazer isso?

Existe algum comando que retorne o número de índice da palavra que eu quero diretamente?

Obrigado.

    
por GJ. 09.06.2012 / 02:47

9 respostas

10

Bash realiza divisão de palavras em strings por si só - na verdade, na maioria das vezes, evitar isso é um problema, e a razão citando é tão importante. É fácil aproveitar isso no seu caso: basta colocar sua string em uma matriz sem citá-la - o bash usará a divisão de palavras para separar os elementos individuais. Supondo que sua string esteja armazenada na variável $str ,

ar=($str) # no quotes!

retornará uma matriz de 5 elementos. Seu índice de matriz é o seu índice de palavras (contando a partir de 0, como na maioria das linguagens de script e programação), ou seja, "Age" é acessado usando

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

ou, se você precisar encontrar o índice do elemento por conteúdo, faça um loop sobre a matriz, por exemplo,

function el_index {
    cnt=0; for el in "${ar[@]}"; do
        [[ $el == "$1" ]] && echo $cnt && break
        ((++cnt))
    done
}
el_index "Age" # => 1
    
por 09.06.2012 / 20:02
3
$ export FOO="Name   Age Sex  ID         Address"

Substituir * Idade por Idade - isso removerá qualquer coisa antes de "Idade":

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

Obtenha qualquer coisa antes de "Idade"

$ echo ${FOO/Age*/}
Name

Obtenha o tamanho dessa string (que é o índice de "Idade"):

$ BEGIN=${FOO/Age*/}
$ echo ${#BEGIN}
7
    
por 09.06.2012 / 12:43
0

Se você não precisa usar estritamente o bash, mas pode usar outros programas comumente encontrados em sistemas com o bash, então você pode usar algo assim:

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

O Python inicia a indexação de strings em zero, portanto, adicionei +1 ao final do comando.

    
por 09.06.2012 / 09:02
0

Você pode usar o regex nativo de 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

Saída

  2 Name
  9 Age
 13 Sex
 20 ID
 29 Address
    
por 09.06.2012 / 10:19
0

Nota : Assumindo aqui que por índice você quer dizer que quer saber qual palavra é (a partir de 0), não qual caractere na string a palavra começa. Outras respostas abordam o último.

Não que eu saiba, mas você pode criar um. Dois truques:

  1. Use as habilidades inatas da construção para para dividir uma entrada não cotada por espaço em branco.
  2. Manuseie o caso em que você não consegue encontrar a coluna desejada. Nesse caso, escolhi enviar o índice encontrado para stout e deixar que o código de status indique se o find foi bem-sucedido. Existem outras possibilidades.

Código:

#!/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
    
por 09.06.2012 / 07:28
0

Experimente o seguinte oneliner de javascript em um shell (use o shell de javascript):

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

Ou com um aqui-doc:

js <<EOF
x = 'Name   Age Sex  ID         Address';
print(x.indexOf('Age'));
EOF
    
por 09.06.2012 / 20:20
0

Eu encontrei uma solução que funciona bem.

$ string='now is the time'
$ buf=the${string#*the}
$ echo $buf
output: the time
$ index=$(( ${#string} - ${#buf} + 1 ))
$ echo $index
output: 8 -> index of first word "the"

Funciona de forma semelhante à função indexOf () em Java, que retorna a primeira ocorrência de uma string de entrada.

Encontrou esta solução aqui link (última postar). Esse cara salvou meu dia. Crédito para ele.

De maneira mais rápida, se você quiser fazer substring a partir do primeiro indexof.

$ a="some long string"
$ b="ri"
$ echo ${a/*$b/$b}
ring
$ echo ${a/$b*/$b}
some long stri

link

    
por 16.07.2013 / 14:54
0

Se os coreutils estiverem disponíveis, você poderá fazê-lo da seguinte maneira:

echo ${str/Age//}| cut -d/ -f1| wc -w

Por solicitação do MariusMatutiae estou adicionando uma explicação sobre como essa operação de 3 etapas funciona:

echo ${str/Age//} 1. replace string which is being searched for unique char (in my case /)

cut -d/ -f1 2. cut off whole part of string which is after unique char

wc -w 3. count and print words which are left this will give us an index number

Para referências, por favor verifique:

link (vá para: "Expansão da variável / Substituição da subcadeia")
link (vá para: "O comando cut" e "invocação wc"

    
por 09.07.2014 / 12:25
0

Uma mistura de duas respostas dadas anteriormente, usando matrizes de bash puro e substituição de substring.

A ideia é obter uma string de todas as palavras antes da que você quer, então contar o número de palavras naquela substring, transformando-a em uma matriz.

$ haystack="Name   Age Sex  ID         Address"
$ words_before=( ${haystack%Age*} )     # truncate string, make array
$ echo ${#words_before[*]}              # count words in array
1

Claro que a idade pode ser armazenada em outra variável needle e, em seguida, use ${haystack%$needle*} . Espere problemas se a palavra que você procurar for um subconjunto de outra palavra, caso em que a resposta de Kopischke ainda está funcionando.

    
por 11.01.2016 / 16:51