2012-03-27 13 views
2

Ich gebe einen Dateinamen in meine Bash-Skript und reinigt den Namen mit sed. Einige Beispieldateien würde:Pad numerische Werte in Dateiname mit dreistelligen Wert mit sed

Test 01.txt 
Test v2 01.txt 

ich zurück bekommen möchten:

Test 001.txt 
Test v002 001.txt 

Hier ist mein Skript

#!/bin/bash 

SAVEIFS=$IFS 
IFS=$(echo -en "\n\b") 
for f in [email protected] 
do 

j=`basename "$f" ".???"` 
BASENAME=`basename "$f" ".???"` 
DIRNAME=`dirname "$f"` 

j=`echo $j |sed -e 's/\///g'` 
j=`echo $j |sed -e 's/_/ /g'` 
j=`echo $j |sed -e 's/^\.//'` 
j=`echo $j |sed -e 's/\[[^()]*\]//g'` 
j=`echo $j |sed -e 's/([^()]*)//g'` 
j=`echo $j |sed -e 's/#//g'` 
j=`echo $j |sed -e 's/+/\ /g'` 
j=`echo $j |sed -e 's/\.\././g'` 
j=`echo $j |sed -e 's/\&/and/g'` 
j=`echo $j |sed -e 's/\ -/-/g'` 
j=`echo $j |sed -e 's/-\ /-/g'` 
j=`echo $j |sed -e 's/-{2,}/-/g'` 
j=`echo $j |sed -r -e 's/\d+/sprintf("%03d",$&)/e'` 
j=`echo $j |sed -e 's/\.\././g'` 
j=`echo $j |sed -e "s/\'//g"` 
j=`echo $j |sed -r -e 's/ {2,}/ /g'` 
j=`echo $j |sed -e 's/\ \././g'` 

if [ "$BASENAME" != "$j" ]; then 
    mv -v "$f" "$DIRNAME"/"$j" 
fi 

done 

Hier ist das Problem Linie

j=`echo $j |sed -r -e 's/\d+/sprintf("%03d",$&)/e'` 

Der Regex funktioniert mit umbenennen, aber nicht mit sed.

+0

Die mehrzeiligen war für meine geistige Gesundheit/Debugging-Prozess. Ein Beispieldateiname wäre: Test 01.txt Ich möchte es in Test 001.txt umbenennen. – CFry

+0

Wenn 'j' anfänglich das Ergebnis von' Basisname' ist, was ist das für: 'j = \ 'echo $ j | sed -e' s/\ /// g '\' '. Nur 'Basisname /' gibt alles aus, was einen Schrägstrich enthält. – Kaz

+0

Diese Zeile war vor der Verwendung von Basisname. Gerade wurde noch nicht entfernt. – CFry

Antwort

2

Statt

sed -r -e 's/\d+/sprintf("%03d",$&)/e' 

Verwendung

perl -pe 's/\d+/sprintf("%03d",$&)/ge' 
+0

Ich bin normalerweise nicht einverstanden, sed perl zu ersetzen, aber ich denke, das ist ein perfektes Beispiel dafür, wenn das eine gute Idee ist. – Kevin

1

Pro Kommentar, Ja, ich verstehe Debugging mit dieser Methode, und das war meine Vermutung.

Es ist fast so einfach, und erfordert später keinen Bereinigungsschritt, um die abschließenden Zeilen und das Zeichen "'" nach unten und oben auf eine Liste wie unten zu verschieben (als alternative Lösung).

j=$(
    echo "$j" \ 
    | sed ' 
    s/\///g 
    s/_/ /g 
    s/^\.// 
    s/\[[^()]*\]//g 
    s/([^()]*)//g 
    s/#//g 
    s/+/\ /g 
    s/\.\././g 
    s/\&/and/g 
    s/\ -/-/g 
    s/-\ /-/g 
    s/-{2,}/-/g 
    s/\.\././g 
    s/'"'"'//g 
    s/ {2,}/ /g 
    s/\ \././g 
' \ 
| awk '/[0-9]/{ 
    match($0,/[0-9][0-9]*/) 
    begin=substr($0,1,RSTART); end=substr($0,RSTART+RLENGTH,length($0)) 
    num=substr($0,RSTART,RSTART+RLENGTH) 
    printf("%s%03d%s", begin,num+0, end) 
    }' 
) 

bearbeiten Es kann möglich sein, auf die entkam einfache Anführungszeichen zu verdoppeln-triple up, das heißt \\' oder \\\', aber ich bin mit dem altbewährten s/'"'"'//g gehen.

Wenn Sie nicht die ursprüngliche Bourne Shell unter Solaris, AIX, HP oder anderen älteren Unix-Programmen verwenden, treten Sie in die 1990er Jahre ein und verwenden Sie das $(...) Konstrukt für die Befehlsersetzung. Backquotes sind seit mindestens "The New Kornshell Programmiersprache", veröffentlicht 1995, veraltet.

Ich hoffe, das hilft.

+0

Danke für die Info. Ich werde mein Skript in diese Richtung bewegen. – CFry

2

Dies könnte für Sie arbeiten (GNU sed):

sed -r 's/[0-9]+/$(printf "%03d" &)/g;s/.*/echo "&"/e' file 
Test 001.txt 
Test v002 001.txt