Respostas:
Você pode usar -b
para 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 -a
switch para dizer ao grep para usar a entrada como texto; necessário ao operar em arquivos binários, e a -o
opçã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=never
para 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 -n1
para 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 0
conforme 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 if
está 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 index
funçã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 index
funçã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, index
retorna 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" '|'`
awk
soluçõ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 expr
soluçã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 awk
soluções podem ser adaptadas para relatar todas as corresponde em cada linha um pouco mais facilmente do que a expr
soluçã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 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 irá dizer-lhe como muitos há como ...
echo $(($#-1))