Linux: Wie Dateinamen (String) per Bash zerlegen?

Hallo,

ich suche eine Möglichkeit einen String per Shellscript in Linux zu zerlegen.

Übergeben wird:
„Status_New_Project_Organisation20120222_083000.xml“

Mich interessieren dabei die numerischen Angaben am Ende, die (wie man vielleicht sieht) das Datum und die Uhrzeit darstellen. Diese Informationen möchte ich aus der Übergabe rausziehen und darstellen als:

„22.02.2012, 08:30 Uhr“

Hatjemand einen Tipp für mich?

Danke,
Hans

Dafür solltest du dir mal die Befehle cut, head und tail angucken.

mit echo "Status_New_Project_Organisation20120222_083000.xml" | cut -d '_' -f 5 „zerschneidest“ du den String am Trennzeichen _ und wählst dann das 5. Feld aus (das wäre im Beispiel die 083000.xml).
Davon kannst du dann mit cut -b 1-2 z.B. die ersten beiden Bytes (08) ausschneiden.
Damit kommst du an die interessanten Stellen des Strings, kannst sie in Variablen speichern und dann entsprechend ausgeben.

Wenn die Anzahl der Unterstriche nicht konstant ist, könntest du auch mit tail -c 11 die letzten 11 Zeichen herausschneiden (Am Ende des Strings ist noch ein newline, das als 11. Zeichen zählt).

hour=`echo "Status_New_Project_Organisation20120222_083000.xml" | tail -c 11 | head -c 2`  
minute=`echo "Status_New_Project_Organisation20120222_083000.xml" | tail -c 11 | cut -b 3-4`  
year=`echo "Status_New_Project_Organisation20120222_083000.xml" | tail -c 20 | cut -b 1-4`  
month=`echo "Status_New_Project_Organisation20120222_083000.xml" | tail -c 20 | cut -b 5-6`  
day=`echo "Status_New_Project_Organisation20120222_083000.xml" | tail -c 20 | cut -b 7-8`  
echo $day'.'$month'.'$year', '$hour':'$minute' Uhr'  

Vielleicht geht es mit sed und regular expressions noch ein wenig effizienter :wink:

Hallo,

ich würd’s mir so zusammenbasteln:

expr substr "Status_New_Project_Organisation20120222_083000.xml" 37 2

das ist dann schon mal der Tag …

Viel Glück!
Daniel

bin kein Shell Profi, aber mit den Befehlen ‚grep ; cut; sed oder awk‘ geht das. Evtl. kombiniert in einer Zeile in etwa so "grep "CPU TEMP" | awk '{print $3}'"

Vielen Dank für den Gedankenanstoss, diese Variante funktioniert für meine Zwecke hervorragend.

Lediglich aus:

hour=`echo "Status_New_Project_Organisation20120222_083000.xml" | tail -c 11 | head -c 2`

Habe ich:

hour=`echo "Status_New_Project_Organisation20120222_083000.xml" | tail -c 11 | cut -b 2`

gemacht.

Status_New_Project_Organisation20120222_083000.xml

22.02.2012, 08:30 Uhr

Die Zahlen von Text und Endung zu trennen ist kein Problem.
Etwas der Art

egrep -o "[0-9]+"

holt dir nur die Zahlen raus.
Wie du dann die Zahlen entsprechend abschneidest und umstellst, kann ich dir aber nicht sagen. Bedenke aber, dass egrep dir ALLE Zahlen rausholt, im restlichen Dateinamen darf also keine Zahl enthalten sein.

Grüße
michi

RESULT=$(  
echo "Status\_New\_Project\_Organisation20120222\_083000.xml" \  
|sed ' s/^.\*\([0-9][0-9][0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\)\_\([0-9][0-9]\)\([0-9][0-9]\)...xml/\3.\2.\1, \4:\5 Uhr/ '  
)  
  
echo $RESULT  
22.02.2012, 08:30 Uhr

ich suche eine Möglichkeit einen String per Shellscript in
Linux zu zerlegen.

Übergeben wird:
„Status_New_Project_Organisation20120222_083000.xml“

„22.02.2012, 08:30 Uhr“

Hallo

hab neulich ein ähnliches Problem gehabt, weil ich Inhalte aus emails automatisiert in eine Excel-Tabelle (bzw. csv-Format) kopieren wollte. Letztlich hab ich das aber dann über ein kleines Java-Programm mit Regex-Vergleichen gemacht. Fand das war in meinem Fall komfortabler, nachdem meine Skript-Versuche nicht richtig funktioniert haben.

Trotzdem hier mal eine Idee, wie man das machen könnte.
Hoffe das meine Kommentare verständlich sind, sonst einfach nochmal melden.

Grüße
zwiggel

#!/bin/bash  
  
STRING="Status_New_Project_Organisation20120222_83000.xml"  
  
# Dateiendung abschneiden  
# beginnt am Stringende "%" und schneide alles "*" bis zum ersten "." ab!  
STRING=${STRING%.*}  
  
# beginnt am Stringanfang "#" und schneidet alles vom ersten Buchstaben [a-zA-Z] bis zum letzten Buchstaben ab.  
# Am Ende dürfen also nach Uhrzeit und Datum keine Buchstaben mehr kommen!  
ONLYNUMBERS=${STRING##[a-zA-Z]\*[a-zA-Z]}  
  
# cut schneidet am Trennzeichen "_" (Option -d)  
# -f1 wählt den ersten Teil und -f2 den zweiten Teil  
DATE=$(echo $ONLYNUMBERS | cut -f1 -d"_")  
TIME=$(echo $ONLYNUMBERS | cut -f2 -d"_")  
  
#20120222 / 10000 = 2012 (kommateil fällt weg!)  
YEAR=$((DATE/10000))  
# 20120222 / 100 = 201202 und 201202%100=02  
# bei $ (modulo) wird auch durch 100 geteilt, aber der Nachkommateil behalten!  
MONTH=$((DATE/100%100))  
DAY=$((DATE%100))  
  
  
TIME=${TIME##0} #evtl führende Null abschneiden, da sonst Division nicht funktioniert!  
HOUR=$((TIME/10000))  
MIN=$((TIME/100%100))  
  
echo "$DAY.$MONTH.$YEAR, $HOUR:blush:MIN Uhr" #Ausgabe: "22.2.2012, 8:30 Uhr"

Hallo

„Status_New_Project_Organisation20120222_083000.xml“
[…]
rausziehen und darstellen als:

„22.02.2012, 08:30 Uhr“

Einige Gegenfragen:

  • Ist der Teil am Anfang (Status_New_Project_Organisation) immer gleich oder ist das ein Platzhalter für die Anfrage?
  • Hast Du Kontrolle über den Dateinamen der Ausgabe (es würde die Dinge vereinfachen, wenn „_“ überall als Trennzeichen verwendet würde)?

Gruss
Sam

Ist schon erledigt, danke. Da der Name vaiabel ist habe ich es per tail und cut gelöst.

Hallo hans,

wenn dein Präfix immer gleich bleibt, kannst du mit

echo $file | sed 's/^.\*Organisation//g' | sed 's/\_.\*//g'

und

echo $file | sed 's/^.\*Organisation.\*\_//g' | sed 's/00\.xml//g'

erstmal auf die relevanten Teile reduzieren. Alternativ kannst du für variable Präfixe auch sed ‚s/[a-Z_]//g‘ verwenden, wenn du allgemeinere Dateinamen ebenfalls zulassen willst. (Musst du halt noch anpassen, wenn du auch Sonderzeichen o.ä. verwenden willst).

Mit

echo $file | cut -c m-n

kann man sich die Zeichen m-n ausgeben lassen, wenn dein Dateiname immer die gleiche Länge hat, bräuchtest du sed nicht unbedingt, andernfalls müsstest du eben wie oben beschrieben zunächst die Zahlen extrahieren. Damit sollte sich dein Problem lösen lassen.

Viel eleganter geht es mit regulären Ausdrücken, umso unverständlicher ist es aber auch, wenn man sich damit nicht auskennt:

echo $file | sed 's/[a-Z\_]\*\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)\_\([0-9]\{2\}\)\([0-9]\{2\}\).\*/\3\.\2\.\1, \4:\5 Uhr/'

Zum Thema reguläre Ausdrücke und sed findet man Unmengen von Material, falls du dich etwas damit vertraut machen möchtest.

Gruß Zorki