# Shell-Script zum umrechnen



## Pollux (10. Januar 2008)

Hi,

ich habe mir ein kleines Shellscript geschrieben, welches mir Untertitel-Dateien formatiert, allerdings hänge ich noch an einer Stelle:



> 1 00;03;49,840 00;03;51,840 ausgang0001.gif



Ich muss jetzt die Werte hinter dem Komma auf Frames umrechnen, sprich: /1000 * 25. Leider weiss ich nicht, wie ich das machen soll. Mit regulären Ausdrücken kann ich die Stelle finden, ich weiss nur nicht, wie ich es umrechnen und dort ausgeben soll.

Weiss jemand Rat?


----------



## olqs (10. Januar 2008)

Kannst du vielleicht mal das komplette Skript posten?
Vielleicht kann man die Umrechnung schon zu nem früheren Zeitpunkt machen und spart sich so das aufsplitten und wieder zusammenbauen der Zeile.


----------



## Pollux (10. Januar 2008)

Nein, an der Stelle hatte ich keine Änderung gemacht. Insgesamt sah die Datei auch ein ganzes Stück anders aus.
Wie kann ich die Zeile denn auseinandernehmen, den Wert berechnen und dann wieder zusammensetzen?


----------



## olqs (10. Januar 2008)

Es geht sicher auch eleganter, aber das ist mal n Beispiel:


```
#!/bin/bash
function calc_frames
{
for pattern in $1
do
  if [[ `echo $pattern | grep ";"` ]];
  then
    echo -n "${pattern%,*},$((${pattern#*,}*25/1000)) "
  else
    echo -n "$pattern "
  fi
done
echo
}

line="1 00;03;49,840 00;03;51,840 ausgang0001.gif"
echo "Original:   $line"
echo -n Umrechnung: `calc_frames "$line"`
```


----------



## Pollux (10. Januar 2008)

Gut, das scheint zu gehen. Wie packe ich das dann wieder in die Datei rein?


----------



## olqs (10. Januar 2008)

Ich würds so machen:


```
while read line
do
  calc_frames "$line"
done <altesfile.txt >neuesfile.txt
```

Du kannst in die while schleife auch "reinpipen":

```
cat altesfile.txt | while read line
do
  calc_frames "$line"
done  >neuesfile.txt
```


----------



## Pollux (10. Januar 2008)

Vielen Dank. Ich merke, dass es fast läuft, aber eine Kleinigkeit verstehe ich noch nicht: Was ist 

```
function calc_frames
	{
	for pattern in $1
```
die $1? Das ist für mein Script bereits ein Aufrufparameter, welche Funktion hat er denn in dieser Function?


----------



## olqs (10. Januar 2008)

In $1 steht der erste Paramter der Funktion. Die Parameter bei Bash Funktionen können/müssen nicht deklariert werden, sondern kann man einfach nutzen.
Ist analog zu den Aufrufparametern bei Shell Skripten.

Wenn du beim Funktionsaufruf nachsiehst wirds klarer:

```
calc_frames "$line"
```
Die Variable $line wird hier übergeben. Um sicherzustellen, dass diese als eine Variable übergeben wird, steht die in "". Ansonsten würden die Leerzeichen in $line Probleme machen.

Wenn du nicht verstehst wieso in deinem Skript zweimal $1 vorkommt, aber das unterschiedliche Werte hat, dann solltest du dich über Variablen Verschattung, Gültigkeitsbereich von Variablen, bzw lokale Variablen informieren.
Es ist nämlich so, dass innerhalb einer Funktion/Subshell Variablen existieren, die nur während des Laufs dieser existieren. Leider finde ich da grad kein anschauliches Beispiel für Bash.
Ich verweise dazu mal auf Advanced Bash Scripting Guide


----------



## Pollux (10. Januar 2008)

Ok, das mit dem Gültigkeitsbereich wusste ich nicht. Ist jetzt aber klar.


```
function calc_frames
	{
	for pattern in $1
	do
	if [[ `echo $pattern | grep ";"` ]];
	then
	echo -n "${pattern%,*},$((${pattern#*,}*25/1000)) "
	else
	echo -n "$pattern "
	fi
	done
	echo
	}

cat $1/ausgang.tmp | while read line
    do
    calc_frames "$line"
    done  >$1/ausgang.tmp2
```

Hier bekomme ich jetzt einen Fehler: 


> line 7: 080: value too great for base (error token is "080")



Sorry, ich glaube, ich stelle mich heute echt etwas blöd an.


----------



## olqs (10. Januar 2008)

Kannst du mal die ausgang.tmp hier als Datei anhängen, dann schau ichs mir morgen mal genauer an.
Ich vermute rgendwas ist da am Format der Zeilen anders.


----------



## Pollux (10. Januar 2008)

Danke für deine Mühe:



> 1 00;03;49,840 00;03;51,840 ausgang0001.gif
> 2 00;03;51,840 00;03;55,080 ausgang0002.gif
> 3 00;03;55,080 00;03;59,189 ausgang0003.gif
> 4 00;04;02,080 00;04;03,789 ausgang0004.gif
> ...


----------



## olqs (11. Januar 2008)

So habe die Funktion nochmal verändert:


```
function calc_frames
{
for pattern in $1
do
  if [[ `echo $pattern | grep ";"` ]];
  then
    temp=${pattern#*,}
    echo -n "${pattern%,*},$((${temp#0}*25/1000)) "
  else
    echo -n "$pattern "
  fi
done
echo
}
```

Das Problem war, dass ${pattern#*,} für die 2te Spalte in der 2ten Zeile eine 080 zurückliefert. Scheinbar behandelt die Bash bei Rechenoperationen Zahlen mit führender 0 als Oktalzahlen. Deshalb die Fehlermeldung.

Durch meine Veränderung wird eine führende 0 entfernt. Wenn hinter dem Komma also mal 008 steht, bekommst du wieder eine ähnliche Fehlermeldung.
Aber das anpassen sollte kein Problem mehr darstellen.


----------



## Pollux (11. Januar 2008)

Danke!
Es wird aber kein Fall eintreten, in dem eine Zahl kleiner als 25 drinsteht (mit Ausnahme der Null, dann ist es aber egal, ob oktal oder dezimal). Ich muss es nur noch hinbekommen, dass ich bei Zahlen < 10 eine führende Null habe.

Vielen Dank.


----------

