Réponses:
Vous pouvez utiliser -b
pour obtenir le décalage d'octet, qui est le même que la position pour le texte simple (mais pas pour UTF-8 ou similaire).
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|
Dans ce qui précède, j'utilise le -a
commutateur pour dire à grep d'utiliser l'entrée comme texte; nécessaire lorsque vous travaillez sur des fichiers binaires, et le -o
commutateur pour sortir uniquement les caractères correspondants.
Si vous ne voulez que la position, vous pouvez utiliser grep pour extraire uniquement la position:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14
Si vous obtenez une sortie bizarre, vérifiez si grep a activé les couleurs. Vous pouvez désactiver les couleurs en passant --colors=never
à grep, ou en préfixant la commande grep avec un \
(qui désactivera tous les alias), par exemple:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14
Pour une chaîne qui renvoie plusieurs correspondances, dirigez-la head -n1
pour obtenir la première correspondance.
Notez que j'utilise les deux dans ce qui précède, et notez que ce dernier ne fonctionnera pas si grep est "aliasé" via un exécutable (script ou autre), uniquement lors de l'utilisation d'alias.
2
;)
^
:)
0:|
comme output-- parce que 0 est la position d'octet de début de la ligne où |
se trouve.
grep (GNU grep) 2.27
. Utilisez-vous peut-être OS X?
Essayer:
printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'
production:
15:|
Cela vous donnera la position avec l'indice basé sur 1.
printf '%s\n' '|' | grep -o . | grep -n '|'
impressions 1
, pas 0
comme prévu.
Si vous utilisez le shell bash , vous pouvez utiliser des opérations purement intégrées sans avoir besoin de générer des processus externes tels que grep ou awk :
$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$
Cela utilise une extension de paramètre pour supprimer toutes les occurrences de |
suivis par n'importe quelle chaîne et l'enregistrer dans une variable temporaire. Il suffit alors de mesurer la longueur de la variable temporaire pour obtenir l'indice de |
.
Notez que if
vérifie si le |
existe dans la chaîne d'origine. Si ce n'est pas le cas, la variable temporaire sera la même que l'original.
Notez également que cela fournit l'index de base zéro |
qui est généralement utile lors de l'indexation de chaînes bash. Cependant, si vous avez besoin de l'index à base unique, vous pouvez le faire:
$ echo $((${#tmp}+1))
15
$
Vous pouvez utiliser la index
fonction awk pour renvoyer la position en caractères où la correspondance se produit:
echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15
Si cela ne vous dérange pas d'utiliser la index
fonction Perl , cela gère le signalement de zéro, une ou plusieurs occurrences d'un caractère:
echo "|abc|xyz|123456|zzz|" | \
perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'
Pour des raisons de lisibilité uniquement, le pipeline a été divisé en deux lignes.
Tant que le caractère cible est trouvé, index
renvoie une valeur positive basée sur zéro (0). Par conséquent, la chaîne "abc | xyz | 123456 | zzz |" lorsque analysé renvoie les positions 0, 4, 8, 15 et 19.
RAMSITALSKHMAN|1|223333
Nous pouvons aussi le faire en utilisant "expr match" ou "expr index"
expr correspond à $ string $ substring où $ substring est un RE.
echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`
Et ci-dessus vous donnera la position car elle renvoie la longueur de la sous-chaîne correspondante.
Mais pour être plus précis dans la recherche d'index:
mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`
awk
solutions peuvent être modifiées de manière triviale pour rapporter ces informations sur chaque ligne d'un fichier (tout ce que vous avez à faire est de supprimer le END
, qui n'a jamais été vraiment nécessaire, de la réponse de JRFerguson, et Avinash Raj le fait déjà) ; alors que pour faire cela avec la expr
solution, vous auriez besoin d'ajouter une boucle explicite (et la réponse de Gnouc n'est pas facilement adaptable pour le faire, du moins je le vois), et (2) les awk
solutions peuvent être adaptées pour rapporter tous les correspond à chaque ligne un peu plus facilement que la expr
solution (en fait, Avinash Raj fait déjà cela aussi).
echo `...`
ici?
$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15
En définissant le séparateur de champs comme chaîne nulle, awk transforme les caractères individuels de l'enregistrement en champs séparés.
quelques alternatives incluent:
similaire à la réponse de Gnouc, mais avec la coquille:
echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \\n |
sh
sh: line 15: syntax error near unexpected token `|
sh: line 15: `|'
avec sed
et dc
éventuellement couvrant plusieurs lignes:
echo 'RAMSITALSKHMAN|1223333' |
sed 's/[^|]/1+/g;s/|/p/;1i0 1+' |dc
15
avec $IFS
...
IFS=\|; set -f; set -- ${0+RAMSITALSKHMAN|1223333}; echo $((${#1}+1))
Cela aussi vous dire combien beaucoup il y a comme ...
echo $(($#-1))