Respostas:
Você pode usar -bpara obter o deslocamento de bytes, que é o mesmo da posição para texto simples (mas não para UTF-8 ou similar).
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|
No exemplo acima, eu uso o -aswitch para dizer ao grep para usar a entrada como texto; necessário ao operar em arquivos binários, e a -oopção para gerar apenas os caracteres correspondentes.
Se você deseja apenas a posição, pode usar grep para extrair apenas a posição:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14
Se você obtiver uma saída estranha, verifique se o grep tem as cores ativadas. Você pode desativar as cores passando --colors=neverpara grep ou prefixando o comando grep com um \(que desativará qualquer apelido), por exemplo:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14
Para uma sequência que retorna várias correspondências, passe head -n1para obter a primeira correspondência.
Observe que eu uso os dois itens acima e observe que este último não funcionará se o grep for "alias" através de um executável (script ou outro), apenas ao usar aliases.
2;)
^:)
0:|como output-- porque 0 é a posição de byte do início da linha onde |é encontrado.
grep (GNU grep) 2.27. Você talvez esteja usando o OS X?
Experimentar:
printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'
resultado:
15:|
Isso fornecerá a posição com o índice baseado em 1.
printf '%s\n' '|' | grep -o . | grep -n '|'imprime 1, não 0conforme o esperado.
Se você estiver usando o shell bash , poderá usar operações puramente internas sem a necessidade de gerar processos externos, como grep ou 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 sequência e salvar em uma variável temporária. É apenas uma questão de medir o comprimento da variável temporária para obter o índice de |.
Observe que ifestá verificando se |existe alguma na string original. Caso contrário, a variável temporária será igual ao original.
Observe também que isso fornece o índice baseado em zero, o |que geralmente é útil na indexação de strings do bash. No entanto, se você precisar do índice baseado em um, poderá fazer o seguinte:
$ echo $((${#tmp}+1))
15
$
Você pode usar a indexfunção do awk para retornar a posição nos caracteres em que a correspondência ocorre:
echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15
Se você não se importa em usar a indexfunção Perl , isso lida com o relato de zero, uma ou mais ocorrências de um personagem:
echo "|abc|xyz|123456|zzz|" | \
perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'
Apenas para facilitar a leitura, o pipeline foi dividido em duas linhas.
Desde que o caractere alvo seja encontrado, indexretorna um valor positivo com base em zero (0). Portanto, a cadeia "abc | xyz | 123456 | zzz |" quando analisado retorna as posições 0, 4, 8, 15 e 19.
RAMSITALSKHMAN|1|223333
Também podemos fazer isso usando "expr match" ou "expr index"
expr corresponde a $ string $ substring em que $ substring é um RE.
echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`
E acima, você fornecerá a posição, pois retorna o comprimento da substring correspondente.
Mas, para ser mais específico na pesquisa de índice:
mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`
awksoluções podem ser modificadas trivialmente para relatar essas informações em todas as linhas de um arquivo (tudo o que você precisa fazer é remover o END, o que nunca foi realmente necessário, da resposta de JRFerguson, e o Avinash Raj já o faz) ; considerando que, para fazer isso com a exprsolução, você precisará adicionar um loop explícito (e a resposta do Gnouc não é facilmente adaptável a isso, pelo que vejo) e (2) as awksoluções podem ser adaptadas para relatar todas as corresponde em cada linha um pouco mais facilmente do que a exprsolução (na verdade, a Avinash Raj já faz isso também).
echo `...`aqui?
$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15
Ao definir o separador de campos como sequência nula, o awk transforma caracteres individuais no registro como campos separados.
algumas alternativas incluem:
semelhante à resposta de Gnouc, mas com a casca:
echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \\n |
sh
sh: line 15: syntax error near unexpected token `|
sh: line 15: `|'
com sede dcpossivelmente 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 irá dizer-lhe como muitos há como ...
echo $(($#-1))