2016-04-22 11 views
1

Ich habe lange Listen wie folgt:bash 0 Pad-Nummern auf Substrings

 
D6N 
T69TN 
K70R 
M184V 
T215FEG 

Das Ergebnis so sein muss:

auf bash
 
D006N 
T069TN 
K070R 
M184V 
T215FEG 

Ich bin neu, habe ich versucht, Ansätze basieren in Aufspaltung es in Spalten und formatieren. Die Positionen und die Länge der zweiten und dritten möglichen Spalten sind jedoch nicht festgelegt. Vielen Dank für jede Hilfe!

+1

Wie konstruieren und drucken Sie Ihre "Liste"? Woher kommt die "Liste"? Vielleicht Bash selbst ist nicht das richtige Werkzeug, aber awk oder sed könnte sein? –

+0

Einverstanden, Bash ist eine Shell, kein Datenprozessor, also wird die Verwendung anderer Tools wie 'awk',' sed', 'grep' usw. wahrscheinlich notwendig sein – edhurtig

+1

@ user3829806 Werden Ihre Zeilen immer im Format' ([AZ] +) ([0-9] +) ([AZ] +) 'und wirst du immer auf die Länge der größten Zahl tippen müssen ... dh die Zahl könnte mehr als 3 Ziffern haben? – edhurtig

Antwort

2

Sie können dies tun awk verwenden, die sich im internen match Funktion:

awk 'match($0, /[0-9]+/) { printf "%s%03d%s\n", 
substr($0, 0, RSTART - 1), substr($0, RSTART, RLENGTH), substr($0, RSTART + RLENGTH) }' file 

Wenn match erfolgreich ist, setzt sie zwei Variablen RSTART und RLENGTH, die verwendet werden können Strings zu extrahieren. Die mittlere Teilzeichenfolge wird unter Verwendung von %03d formatiert, um mit führenden Nullen zu puffern.

Alle Zeilen, die nicht mit dem Muster übereinstimmen, werden nicht gedruckt.

Eine weitere Option mit Perl:

perl -pe 's/\d{1,3}/sprintf("%03d", $&)/eg' file 

Diese mit einer Reihe mit Nullen aufgefüllt dreistelligen beliebige Folge von einer bis drei Ziffern ersetzt. In dieser Version werden alle Zeilen gedruckt.

+0

Oh, mir hat das Perl gefallen ... Kluge Arbeit mit '/ e' :-) – anishsane

+0

Tatsächlich funktioniert die Perl-Version schnell und reibungslos! Vielen Dank. – user3829806

0

Es ist etwas länger mit den sed ‚s regulären Ausdrücke, aber hier ist es in Perl:

echo "D6N" | perl -pe 's/(\D)(\d)(\D)/${1}0$2$3/g; s/(\D)(\d\d)(\D)/${1}0$2$3/g;' 

Es wäre Pad mit Nullen 1- und 2-stellige Zahlen von Nicht-Ziffern umgeben. Es macht es mit einem einfachen Trick: Pad 1-stellige Zahlen mit einer Null (also 1-stellige Zahlen werden 2-stellige Zahlen), und dann Pad 2-stellige Zahlen mit einer anderen Null.

0

AFAIK, es gibt dafür keine einfache pure-Bash-Lösung. Daher würde ich Perl bevorzugen, weil Perl-Ausdrücke kurz sind und Perl allgegenwärtig ist.

s='D6N 
T69TN 
K70R 
M184V 
T215FEG' 

echo "$s" | perl -ne '/^(\D*)(\d{1,2})(\D*)$/m and printf "%s%03s%s", $1, $2, $3 or print' 
+0

Obwohl dieser Code die Frage beantworten kann, zusätzlichen Kontext in Bezug auf _why_ und/oder _how_ es Antworten bietet die Frage würde erheblich verbessern seine langfristige Wert. Bitte [bearbeiten] Sie Ihre Antwort, um eine Erklärung hinzuzufügen. –

0

Eine weitere sed basierte Implementierung:

$ cat testfile 
D6N 
T69TN 
K70R 
M184V 
T215FEG 

$ sed -r 's/[0-9]+/00&/g; s/0?0?([0-9]{3})/\1/g' testfile 
D006N 
T069TN 
K070R 
M184V 
T215FEG 

Logic: Bedingungslos Präfix 2 Nullen Zahlen & entfernen führenden Nullen, bis die Nummer 3 Ziffer lang ist.

0

Dieses Gnu awk kann auch den Job erledigen:

awk -v RS='[0-9]+' 'RT{print $0 sprintf("%03d", RT); next} 1' ORS= file 

D006N 
T069TN 
K070R 
M184V 
T215FEG 
0

Mit Bash Regexes:

#!/bin/bash 

re='([[:alpha:]]*)([[:digit:]]*)([[:alpha:]]*)' 

while IFS= read -r line; do 
    [[ $line =~ $re ]] 
    printf "%s%03d%s\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}" 
done < infile 

Diese jede Zeile übereinstimmt mit einem regulären Ausdruck und fängt die drei Gruppen: Buchstaben, Ziffern, Buchstaben . Die Formatzeichenkette printf stellt sicher, dass die Zifferngruppe Null ist, wenn sie kürzer als drei Ziffern ist.