Risposte:
È possibile utilizzare -b
per ottenere l'offset di byte, che è uguale alla posizione per il testo semplice (ma non per UTF-8 o simile).
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|
In quanto sopra, uso l' -a
interruttore per dire a grep di usare l'input come testo; necessario quando si opera su file binari e l' -o
opzione per stampare solo i caratteri corrispondenti.
Se vuoi solo la posizione, puoi usare grep per estrarre solo la posizione:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14
Se ottieni un output strano, controlla se grep ha i colori abilitati. Puoi disabilitare i colori passando --colors=never
a grep o aggiungendo il prefisso grep al comando con un \
(che disabiliterà tutti gli alias), ad esempio:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14
Per una stringa che restituisce più corrispondenze, esegui il pipe through head -n1
per ottenere la prima corrispondenza.
Nota che io uso entrambi in quanto sopra e nota che quest'ultimo non funzionerà se grep è "aliasato" attraverso un eseguibile (script o altro), solo quando si usano gli alias.
2
;)
^
:)
0:|
come output-- perché 0 è la posizione in byte dell'inizio della riga in cui |
si trova.
grep (GNU grep) 2.27
. Stai forse usando OS X?
Provare:
printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'
produzione:
15:|
Questo ti darà la posizione con index based-1.
printf '%s\n' '|' | grep -o . | grep -n '|'
stampe 1
, non 0
come previsto.
Se stai usando la shell bash , puoi usare operazioni puramente integrate senza la necessità di generare processi esterni come grep o awk :
$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$
Questo utilizza un'espansione dei parametri per rimuovere tutte le occorrenze di |
follow da qualsiasi stringa e salvarle in una variabile temporanea. È quindi solo una questione di misurare la lunghezza della variabile temporanea per ottenere l'indice di |
.
Nota che if
sta controllando se |
esiste assolutamente nella stringa originale. In caso contrario, la variabile temporanea sarà la stessa dell'originale.
Nota anche questo fornisce l'indice a base zero di |
cui è generalmente utile quando si indicizzano stringhe bash. Tuttavia, se si richiede l'indice a base singola, è possibile eseguire questa operazione:
$ echo $((${#tmp}+1))
15
$
È possibile utilizzare la index
funzione di awk per restituire la posizione in caratteri in cui si verifica la corrispondenza:
echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15
Se non ti dispiace usare la index
funzione Perl , questo gestisce la segnalazione di zero, una o più occorrenze di un personaggio:
echo "|abc|xyz|123456|zzz|" | \
perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'
Per motivi di leggibilità, solo, la pipeline è stata suddivisa su due righe.
Finché viene trovato il personaggio bersaglio, index
restituisce un valore positivo basato su zero (0). Quindi, la stringa "abc | xyz | 123456 | zzz |" quando analizzato restituisce le posizioni 0, 4, 8, 15 e 19.
RAMSITALSKHMAN|1|223333
Possiamo anche farlo usando "corrispondenza expr" o "indice expr"
expr corrisponde a $ string $ sottostringa dove $ sottostringa è un RE.
echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`
E sopra ti darà la posizione perché restituisce la lunghezza della sottostringa abbinata.
Ma per essere più specifici per la ricerca dell'indice:
mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`
awk
soluzioni possono essere banalmente modificate per riportare queste informazioni su ogni riga di un file (tutto ciò che devi fare è rimuovere il END
, che non è mai stato veramente necessario, dalla risposta di JRFerguson, e Avinash Raj lo fa già) ; considerando che, per farlo con la expr
soluzione, è necessario aggiungere un ciclo esplicito (e la risposta di Gnouc non è facilmente adattabile per farlo, quello che vedo), e (2) le awk
soluzioni possono essere adattate per riportare tutte le corrispondenze in ciascuna riga un po 'più facilmente della expr
soluzione (in effetti, anche Avinash Raj lo fa già).
echo `...`
qui?
$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15
Impostando il separatore di campo come stringa nulla, awk trasforma il singolo carattere nel record come campi separati.
alcune alternative includono:
simile alla risposta di Gnouc, ma con la shell:
echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \\n |
sh
sh: line 15: syntax error near unexpected token `|
sh: line 15: `|'
con sed
e dc
possibilmente che si estende su più righe:
echo 'RAMSITALSKHMAN|1223333' |
sed 's/[^|]/1+/g;s/|/p/;1i0 1+' |dc
15
con $IFS
...
IFS=\|; set -f; set -- ${0+RAMSITALSKHMAN|1223333}; echo $((${#1}+1))
Che vi dirà anche come quanti ci sono come ...
echo $(($#-1))