Extrahieren von Nummern aus Dateinamen

Extrahieren von Nummern aus Dateinamen

Ich habe einen Dateinamen nach diesem Modell:

 1.raw_bank_details_211.trg
 2.raw_bank_details_222.trg

Ich muss den cutBefehl in Unix verwenden und die obige Zeichenfolge ausschneiden, um sie zu erhalten 211 und 222aus den Zeichenfolgen den Wert wiederzugeben.

Ich habe grep bereits verwendet grep -o -E '[0-9]+'und brauche eine Alternative dazu.

Antwort1

Sie wären besser dran, wenn Sie ein Standard-Textverarbeitungstool anstelle eines naiven Tools wie verwenden würden cut.

Hier sind einige Möglichkeiten:


Mit awkwird das durch _oder .getrennte vorletzte Feld abgerufen:

awk -F '[_.]' '{print $(NF-1)}' file.txt

grepmit PCRE ( -P):

grep -Po '\d+(?=[^_]*$)' file.txt
  • -oerhält nur den passenden Teil

  • \d+stimmt mit einer oder mehreren Ziffern überein

  • Der positive Lookahead mit Nullbreite (?=[^_]*$)stellt sicher, dass _bis zum Ende der Zeile kein folgt.


Mit sed:

sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
  • .*_passt zu allem bis zuletzt_

  • ([[:digit:]]+)stimmt mit den erforderlichen Ziffern überein und wird in die erfasste Gruppe eingefügt

  • .*passt zum Rest

  • Beim Ersetzen \1wird nur die erfasste Gruppe verwendet .


Mit perl, gleiche Logik wie sedbei :

perl -pe 's/.*_(\d+).*/$1/' file.txt 

Wenn Sie verwenden müssen cut, tun Sie dies in zwei Schritten: Holen Sie sich zuerst das _getrennte 4. Feld und dann das .getrennte 1. Feld:

cut -d_ -f4 file.txt | cut -d. -f1

Dies wird nicht empfohlen, da dies eine Festcodierung der Feldnummern erfordert.


Wenn es ein String wäre, würde ich es mithilfe der Shell-Parametererweiterung machen:

% str='1.raw_bank_details_211.trg'

% str=${str##*_} 

% echo "${str%%.*}"
211

Sie können immer noch eine whileKonstruktion verwenden und jede Zeile in eine Variable übernehmen und dies tun, aber das wäre bei einer großen Datei langsam. Alternativ können Sie auch _.as the verwenden IFSund stattdessen das fest codierte Feld (wie cut) abrufen, wenn Sie möchten.


Beispiel:

% cat file.txt                          
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg

% awk -F '[_.]' '{print $(NF-1)}' file.txt
211
222

% grep -Po '\d+(?=[^_]*$)' file.txt         
211
222

% sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
211
222

% perl -pe 's/.*_(\d+).*/$1/' file.txt 
211
222

% cut -d_ -f4 file.txt | cut -d. -f1
211
222

Antwort2

cutist dafür das falsche Werkzeug. Um kurze Strings wie Dateinamen zu manipulieren, verwenden Sie nach Möglichkeit die String-Manipulationsfunktionen der Shell. Alle sh-artigen Shells¹ (sh, dash, bash, ksh, zsh, …) verfügen über einige grundlegende String-Manipulationen als Teil der Variablensubstitution. Siehe z. B. dieDash-Handbuchunter „Parametererweiterung“. Sie können das kürzeste/längste Präfix/Suffix entfernen, das einem Muster entspricht.

Sie möchten die letzte Ziffernfolge im Dateinamen, also:

  1. Bestimmen Sie das nicht numerische Suffix, indem Sie alles bis zur letzten Ziffer entfernen.
  2. Entfernen Sie dieses Suffix.
  3. Entfernen Sie alles bis zur letzten Nicht-Ziffer.
filename=1.raw_bank_details_211.trg
suffix="${filename##*[0-9]}"
number="${filename%"$suffix"}"
number="${number##*[!-0-9]}"

¹ Außer einigen Bourne-Shells vor POSIX, aber die sind Ihnen egal.

verwandte Informationen