Como encontrar uma posição de um personagem usando o grep?

10

Eu preciso identificar a posição de um caractere em string usando o comando grep.

Exemplo, a string é RAMSITALSKHMAN|1223333 .

grep -n '[^a-zA-Z0-9\$\~\%\#\^]'

Como encontro a posição de | na string dada?

    
por user82782 02.09.2014 / 16:44

7 respostas

26

Você pode usar -b para obter o deslocamento de bytes, que é o mesmo que a posição para texto simples (mas não para UTF-8 ou similar).

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|

Acima, eu uso a opção -a para dizer ao grep para usar a entrada como texto; necessário ao operar em arquivos binários, e a opção -o somente exibe os caracteres correspondentes.

Se você quer apenas a posição, você pode usar o grep para extrair apenas a posição:

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14

Se você obtiver resultados estranhos, verifique se o grep tem cores ativadas. Você pode desabilitar as cores passando --colors=never para grep ou prefixando o comando grep com \ (o que desabilitará todos os aliases), por exemplo:

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14

Para uma string que retorna várias correspondências, passe por head -n1 para obter a primeira correspondência.

Note que eu uso os dois acima, e note que o último não irá funcionar se o grep for "aliado" através de um executável (script ou outro), somente quando usar aliases.

    
por 02.09.2014 / 20:18
11

Tente:

printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'

saída:

15:|

Isso lhe dará a posição com o índice baseado em 1.

    
por 02.09.2014 / 16:54
8

Se você estiver usando o shell , você pode usar operações integradas sem a necessidade de gerar processos externos, como ou < href="/ questions / tagged / awk" class="post-tag" title="mostrar perguntas marcadas 'awk'"> awk :

$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$ 

Isso usa uma expansão de parâmetro para remover todas as ocorrências de | segue por qualquer string e salva isso em uma variável temporária. É então apenas uma questão de medir o comprimento da variável temporária para obter o índice de | .

Observe que if está verificando se o | existe na cadeia original. Se não, então a variável temporária será a mesma que a original.

Observe também que isso fornece o índice baseado em zero de | , que geralmente é útil ao indexar strings bash. No entanto, se você precisar do índice baseado em um, poderá fazer isso:

$ echo $((${#tmp}+1))
15
$ 
    
por 02.09.2014 / 19:51
4

Você pode usar a função index do awk para retornar a posição em caracteres onde a correspondência ocorre:

echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15

Se você não se importa em usar a função index do Perl, isso trata de zero, uma ou mais ocorrências de um caractere:

echo "|abc|xyz|123456|zzz|" | \
perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'

Para facilitar a leitura, apenas o pipeline foi dividido em duas linhas.

Contanto que o caractere de destino seja encontrado, index retornará um valor positivo com base em zero (0). Daí a string "abc | xyz | 123456 | zzz |" quando analisado retorna as posições 0, 4, 8, 15 e 19.

    
por 02.09.2014 / 16:57
3

Também podemos fazer isso usando "expr match" ou "expr index"

expr match $ string $ substring onde $ substring é um RE.

echo 'expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|''

E acima, você terá a posição porque retorna o comprimento da substring correspondente.

Mas para ser mais específico para o índice de pesquisa:

mystring="RAMSITALSKHMAN|122333"
echo 'expr index "$mystring" '|''
    
por 02.09.2014 / 16:58
2

Outro comando do awk ,

$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15

Ao definir o separador de campos como string nula, o awk transforma caracteres individuais no registro como campos separados.

    
por 02.09.2014 / 17:38
2

algumas alternativas incluem:

semelhante à resposta de Gnouc, mas com o shell:

echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \n | 
sh

sh: line 15: syntax error near unexpected token '|
sh: line 15: '|'

com sed e dc possivelmente abrangendo várias linhas:

echo 'RAMSITALSKHMAN|1223333' |
sed 's/[^|]/1+/g;s/|/p/;1i0 1+' |dc

15

com $IFS ...

IFS=\|; set -f; set -- ${0+RAMSITALSKHMAN|1223333}; echo $((${#1}+1))

Isso também informará como muitos são como ...

echo $(($#-1))
    
por 03.09.2014 / 13:06