it-swarm.com.de

Wie finde ich eine Position eines Charakters mit grep?

Ich muss die Position eines Zeichens in einer Zeichenfolge mit dem Befehl grep identifizieren.

Beispiel: Die Zeichenfolge lautet RAMSITALSKHMAN|1223333.

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

Wie finde ich die Position von | In der angegebenen Zeichenfolge?

10
user82782

Sie können -b Verwenden, um den Byte-Offset abzurufen, der der Position für einfachen Text entspricht (jedoch nicht für UTF-8 oder ähnliches).

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

Oben verwende ich den Schalter -a, Um grep anzuweisen, die Eingabe als Text zu verwenden. erforderlich, wenn Binärdateien bearbeitet werden, und der Schalter -o gibt nur die übereinstimmenden Zeichen aus.

Wenn Sie nur die Position möchten, können Sie mit grep nur die Position extrahieren:

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

Wenn Sie eine seltsame Ausgabe erhalten, überprüfen Sie, ob für grep Farben aktiviert sind. Sie können Farben deaktivieren, indem Sie --colors=never An grep übergeben oder dem Befehl grep ein \ Voranstellen (wodurch alle Aliase deaktiviert werden), z.

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

Für eine Zeichenfolge, die mehrere Übereinstimmungen zurückgibt, führen Sie head -n1 Durch, um die erste Übereinstimmung zu erhalten.

Beachten Sie, dass ich beide oben verwende und dass letzteres nicht funktioniert, wenn grep über eine ausführbare Datei (Skript oder auf andere Weise) "aliasiert" wird, nur wenn Aliase verwendet werden.

28
runejuhl

Versuchen:

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

ausgabe:

15:|

Dies gibt Ihnen die Position mit indexbasiert-1.

11
cuonglm

Wenn Sie die bash Shell verwenden, können Sie rein integrierte Operationen verwenden, ohne externe Prozesse wie grep oder awk erzeugen zu müssen ::

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

Dies verwendet ein Parametererweiterung , um alle Vorkommen von | Zu entfernen, gefolgt von einer beliebigen Zeichenfolge, und diese in einer temporären Variablen zu speichern. Es ist dann nur noch eine Frage der Länge der temporären Variablen, um den Index von | Zu erhalten.

Beachten Sie, dass if prüft, ob | In der ursprünglichen Zeichenfolge überhaupt vorhanden ist. Ist dies nicht der Fall, entspricht die temporäre Variable der ursprünglichen.

Beachten Sie auch, dass dies den auf Null basierenden Index von | Bereitstellt, der im Allgemeinen beim Indizieren von Bash-Strings nützlich ist. Wenn Sie jedoch den einbasierten Index benötigen, können Sie dies tun:

$ echo $((${#tmp}+1))
15
$ 
8
Digital Trauma

Sie können die Funktion index von awk verwenden, um die Position in Zeichen zurückzugeben, an denen die Übereinstimmung auftritt:

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

Wenn es Ihnen nichts ausmacht, die index -Funktion von Perl zu verwenden, werden hiermit null, ein oder mehrere Vorkommen eines Zeichens gemeldet:

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

Nur zur besseren Lesbarkeit wurde die Pipeline auf zwei Zeilen aufgeteilt.

Solange das Zielzeichen gefunden wird, gibt index einen positiven Wert zurück, der auf Null (0) basiert. Daher ist die Zeichenfolge "abc | xyz | 123456 | zzz |" Wenn analysiert, werden die Positionen 0, 4, 8, 15 und 19 zurückgegeben.

4
JRFerguson

Wir können es auch mit "expr match" oder "expr index" machen.

ausdruck entspricht $ string $ Teilzeichenfolge, wobei $ Teilzeichenfolge eine RE ist.

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

Und oben erhalten Sie die Position, da die Länge des übereinstimmenden Teilstrings zurückgegeben wird.

Genauer gesagt für die Suche nach Index:

mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`
3
bluefoggy

Ein weiterer awk-Befehl ,

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

Durch Festlegen des Feldtrennzeichens als Nullzeichenfolge verwandelt awk einzelne Zeichen im Datensatz als separate Felder.

2
Avinash Raj

einige Alternativen sind:

ähnlich wie Gnoucs Antwort, aber mit der Shell:

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

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

mit sed und dc, die möglicherweise mehrere Zeilen umfassen:

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

15

mit $IFS...

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

Das wird dir auch sagen, wie viele es gibt wie ...

echo $(($#-1))
2
mikeserv