Regex, der Zahlen nach einer bestimmten Zeichenfolge abtastet

8

Also habe ich eine Zeile:

ID: 54376

Können Sie mir helfen, einen regulären Ausdruck zu erstellen, der nur Zahlen ohne "ID:" zurückgibt?

HINWEIS: Diese Zeichenfolge befindet sich in einer Datei.

Blake Gibbs
quelle

Antworten:

13

Versuche dies:

grep -oP '(?<=ID: )[0-9]+' file

oder:

perl -nle 'print $1 if /ID:.*?(\d+)/' file
cuonglm
quelle
Vielen Dank für die Antwort, aber ich brauche nicht alle Nummern aus einer Datei, sondern nur eine Nummer, die nach ID auftritt:
Blake Gibbs
Meine Antwort wurde aktualisiert.
Cuonglm
1
Beachten Sie, dass -ound -PGNU-Erweiterungen zu sind grep. -ofunktioniert auch auf den BSDs. PCRE-Unterstützung mit -Pwird auch nicht immer kompiliert.
Matt
4

Verwenden Sie diese Option egrepmit -ooder grepmit -Eo, um nur das übereinstimmende Segment abzurufen. Verwenden Sie [0-9]als Regex, um nur Zahlen zu erhalten:

grep -Eo [0-9]+ filename
Rohit Jain
quelle
1
Das OP muss erst nach einer bestimmten Zeichenfolge übereinstimmen. Siehe den Titel der Frage.
Terdon
4

Es gibt viele Möglichkeiten, dies zu tun. Zum Beispiel:

  1. Verwenden Sie GNU grepmit aktuellen PCREs und stimmen Sie die folgenden Zahlen ab ID::

    grep -oP 'ID:\s*\K\d+' file
    
  2. Verwenden Sie awkund drucken Sie einfach das letzte Feld aller Zeilen, die mit beginnenID:

    awk '/^ID:/{print $NF}' file
    

    Dadurch werden auch Felder gedruckt, die keine Zahlen sind, um nur Zahlen zu erhalten, und nur im zweiten Feld verwenden

    awk '($1=="ID:" && $2~/^[0-9]+$/){print $2}' file
    
  3. Verwenden Sie GNU grep mit erweiterten regulären Ausdrücken und analysieren Sie es zweimal:

    grep -Eo '^ID: *[0-9]+' file | grep -o '[0-9]*'
    
terdon
quelle
Vielen Dank! Was \Kmacht das erste Beispiel?
rnd_d
2
@rnd_d ist ein PCRE-Konstrukt (Perl Compatible Regular Expressions), das bedeutet, dass "alles ignoriert wird, was bis zu diesem Punkt übereinstimmt". Es wird wie ein Lookbehind verwendet. Ich kann damit -onur den passenden Teil drucken, aber auch Dinge verwerfen, an denen ich nicht interessiert bin. Vergleiche echo "foobar" | grep -oP "foobar"undecho "foobar" | grep -oP 'foo\Kbar'
terdon
4
sed -n '/ID: 54376/,${s/[^ 0-9]*//g;/./p}'

Dadurch werden nur alle Zahlen und Leerzeichen gedruckt, die nach ID: 54376einer Dateieingabe auftreten.

Ich habe das Obige gerade ein wenig aktualisiert, um es ein wenig schneller zu machen *und keine pleeren Zeilen zu drucken, nachdem die nicht {numerischen, Leerzeichen} Zeichen entfernt wurden.

Es adressiert Zeilen von Regex /ID: 54376/ ,bis zum $letzten und s///entfernt darauf alle oder einige *Zeichen, die ^nicht gedruckt werden , [^ 0-9]*und pdruckt dann /keine /Zeile mit einem .verbleibenden Zeichen.

DEMO:

{
echo line 
printf 'ID: 54376\nno_nums_or_spaces\n'
printf '%s @nd 0th3r char@cter$ %s\n' $(seq 10)
echo 'ID: 54376'
} | sed -n '/ID 54376/,${s/[^ 0-9]*//g;/./p}'

AUSGABE:

 54376
1  03  2
3  03  4
5  03  6
7  03  8
9  03  10
 54376
mikeserv
quelle
1

Mit sed:

{
    echo "ID: 1"
    echo "Line doesn't start with ID: "
    echo "ID: Non-numbers"
    echo "ID: 4"
} | sed -n '/^ID: [0-9][0-9]*$/s/ID: //p'

Das -nist "standardmäßig nichts drucken", das /^ID: [0-9][0-9]*$/ist "für Zeilen, die diesem regulären Ausdruck entsprechen" (beginnt mit "ID:", dann 1 oder mehr Ziffern, dann Zeilenende), und das s/ID: //pist von der Form s/pattern/repl/flags- sbedeutet wir Ersetzen Sie das Muster "ID: "durch Ersetzungstext ""(leere Zeichenfolge) mithilfe des pFlags. Dies bedeutet "Diese Zeile nach dem Ersetzen drucken".

Ausgabe:

1
4
godlygeek
quelle
Es funktioniert nicht, wenn die ID in der Mitte einer Zeile vorhanden ist.
Avinash Raj
Auch sollte es nicht, basierend auf meiner Lektüre der Frage. Und wenn Sie nicht versuchen, diesen Fall vorzeitig zu behandeln, wird der Code einfacher und portabler.
Godlygeek
0

Ein weiterer GNU sed Befehl,

sed -nr '/ID: [0-9]+/ s/.*ID: +([0-9]+).*/\1/p' file

Es druckt eine beliebige Zahl nach ID:

Avinash Raj
quelle
Das brauchst du wirklich nicht +. Wenn der Unterschied zwischen einem Zeichen und 3 Zeichen darin besteht, dass Ihr Skript möglicherweise nicht in allen seds funktioniert , sollten Sie wahrscheinlich Folgendes tun : sed -n '/ID: \([0-9][0-9]*\).*/{s//\1/;s/.*[^0-9]//;/./p}'. Ihre Antwort verfehlt auch die erste ID: [0-9]in einer Zeile, die zwei Vorkommen von enthält ID: [0-9].
Mikesserv
0

Verwenden Sie grep + awk:

  grep "^ID" your_file | awk {'print $2'}

Bonus: leicht zu lesen :)

Lilie
quelle
1
Sie brauchen nicht, grepwenn Sie verwenden awk. awk '/^ID/ { print $2 }'macht das Gleiche und vermeidet Probleme mit der Grep-Zeilenpufferung . Es ist auch so ziemlich das Gleiche wie eine der Lösungen in @ terdons Antwort.
Cas