Variableninhalt wird nicht gespeichert

G

Gast123

Hallo Leute,

ich habe ein seltsames Problem, dass in einem Shellskript eine Funktion den Inhalt einer Variablen nicht dauerhaft speichert.
Das Skript befindet sich mit einer Beispieldatei im Anhang.
Ich habe im Skript bereits echos eingebaut um den Status der Variable abzufragen.
Es geht um die Variable "BPM", die man als zweiten Parameter dem Skript übergeben kann, oder als erste Zeile in die Musikdatei schreiben kann, oder sonst den Standardwert "120" annimmt.
Ich stehe echt auf dem Schlauch, warum das in der Funktion "play_note" funktioniert, nicht aber in "lineOK".
Vielleicht könnt ihr mir helfen.

Beste Grüße
Schard

Script:
Code:
#! /bin/bash

export BPM=""

noteOK() {
	return 0
}

setBPM() {
	echo "BPM=$BPM"
	if [ -n "$1" ]; then
		if [ -z "$BPM" ]; then
			BPM=$1
			echo Set BPM to "$BPM"
		fi
	fi
}

timeOK() {	
	TIME=$@
	# Note length must be between 1 and 16
	if [ $TIME -ge 1 ]; then
		if [ $TIME -le 16 ]; then
			return 0
		else
			echo -e "ERROR:\tLength too long!" >&2
			return 1
		fi
	else
		echo -e "ERROR:\tLength too short!" >&2
		return 2
	fi
}

lineOK() {
	LINE="$@"
	if [ "$LINE" == "$(echo -e "`echo "$LINE" | cut -f 1`\t`echo "$LINE" | cut -f 2`")" ]; then
		if (noteOK) ; then
			if (timeOK `echo "$LINE" | cut -f 2`) ; then
				return 0
			fi
		fi
	# First line may specify fix BPM for the music
	elif [ "$LINE" == "`echo "$LINE" | cut -f 1`" ]; then
		if [ -z "$BPM" -a -n "$LINE" ]; then
			setBPM `echo "$LINE" | cut -f 1`
		fi
		return 1
	fi
	return 2
}

# Decode node to its specific frequency
tone() {
	case "$1" in
		"AA")	echo "220.0";;
		"BB"|"HH")	echo "246.9";;
		"C")	echo "261.6";;
		"C#")	echo "277.2";;
		"D")	echo "293.7";;
		"D#")	echo "311.1";;
		"E")	echo "329.6";;
		"F")	echo "349.2";;
		"F#")	echo "370.0";;
		"G")	echo "392.0";;
		"G#")	echo "415.3";;
		"A")	echo "440.0";;
		"A#")	echo "466.2";;
		"B"|"H")	echo "493.9";;
		"c")	echo "523.2";;
		"c#")	echo "554.4";;
		"d")	echo "587.4";;
		"d#")	echo "622.2";;
		"e")	echo "659.2";;
		"f")	echo "698.4";;
		"f#")	echo "740.0";;
		"g")	echo "784.0";;
		"g#")	echo "830.6";;
		"a")	echo "880.0";;
		"a#")	echo "932.4";;
		"b"|"h")	echo "987.8";;
		# Pauses are at 1 Hz (not hearable)
		"p"|"P")	echo "1";;
		*)	echo "$1"
	esac
}

# Play a note for a certain time
play_note() {
	# Default BPM (if neither specified as argument, nor in music file)
	setBPM 120
	BPMS=$((60*1000/$BPM))
	TONE=$1
	LENGTH=$2
	TIME=$(($BPMS*$LENGTH/16))

	beep -f `tone $TONE` -l $TIME
}

play() {
	FILE="$1"

	while read LINE; do
		if (lineOK "$LINE") ; then
			echo "BPM=$BPM"
			play_note $LINE
		fi
	done < $FILE
}

FILE="$1"

if [ -f "$FILE" ]; then
	setBPM $2
	play "$FILE"
else
	echo -e "ERROR:\tMusic file not found" 1>&2
fi

Beispiel-Music File:
Code:
100
G	8
F	4
E	8
D	8
C	8
D	8
E	8
C	8
D	4
E	4
F	4
D	4
E	12
D	4
C	8
BB	8
C	8
 
Zuletzt bearbeitet von einem Moderator:
Hm,

interessanter Weise geht es, wenn ich in "play()" "lineOK()" außerhalb der if-Abfrage aufrufe:
Code:
#! /bin/bash

BPM=""

FILE="$1"

noteOK() {
	return 0
}

setBPM() {
	echo "BPM=$BPM"
	if [ -n "$1" ]; then
		if [ -z "$BPM" ]; then
			BPM=$1
			echo -e "Set BPM to \"$BPM\""
		fi
	fi
}

timeOK() {	
	TIME=$@
	# Note length must be between 1 and 16
	if [ $TIME -ge 1 ]; then
		if [ $TIME -le 16 ]; then
			return 0
		else
			echo -e "ERROR:\tLength too long!" >&2
			return 1
		fi
	else
		echo -e "ERROR:\tLength too short!" >&2
		return 2
	fi
}

lineOK() {
	LINE="$@"
	if [ "$LINE" == "$(echo -e "`echo "$LINE" | cut -f 1`\t`echo "$LINE" | cut -f 2`")" ]; then
		if (noteOK) ; then
			if (timeOK `echo "$LINE" | cut -f 2`) ; then
				return 0
			fi
		fi
	# First line may specify fix BPM for the music
	elif [ "$LINE" == "`echo "$LINE" | cut -f 1`" ]; then
		if [ -z "$BPM" -a -n "$LINE" ]; then
			setBPM `echo "$LINE" | cut -f 1`
		fi
		return 1
	fi
	return 2
}

# Decode node to its specific frequency
tone() {
	case "$1" in
		"AA")	echo "220.0";;
		"BB"|"HH")	echo "246.9";;
		"C")	echo "261.6";;
		"C#")	echo "277.2";;
		"D")	echo "293.7";;
		"D#")	echo "311.1";;
		"E")	echo "329.6";;
		"F")	echo "349.2";;
		"F#")	echo "370.0";;
		"G")	echo "392.0";;
		"G#")	echo "415.3";;
		"A")	echo "440.0";;
		"A#")	echo "466.2";;
		"B"|"H")	echo "493.9";;
		"c")	echo "523.2";;
		"c#")	echo "554.4";;
		"d")	echo "587.4";;
		"d#")	echo "622.2";;
		"e")	echo "659.2";;
		"f")	echo "698.4";;
		"f#")	echo "740.0";;
		"g")	echo "784.0";;
		"g#")	echo "830.6";;
		"a")	echo "880.0";;
		"a#")	echo "932.4";;
		"b"|"h")	echo "987.8";;
		# Pauses are at 1 Hz (not hearable)
		"p"|"P")	echo "1";;
		*)	echo "$1"
	esac
}

# Play a note for a certain time
play_note() {
	# Default BPM (if neither specified as argument, nor in music file)
	setBPM 120
	BPMS=$((60*1000/$BPM))
	TONE=$1
	LENGTH=$2
	TIME=$(($BPMS*$LENGTH/16))

	beep -f `tone $TONE` -l $TIME
}

play() {
	while read LINE; do
		lineOK "$LINE"
		if ($?) ; then
			echo "BPM=$BPM"
			play_note $LINE
		fi
	done < $FILE
}

if [ -f "$FILE" ]; then
	setBPM $2
	play "$FILE"
else
	echo -e "ERROR:\tMusic file not found" 1>&2
fi
 
Hi Schard!

Bei deinem letzten Beispiel fehlt, im Gegensatz zum ersten Beispiel, in der Funktion play() das FILE="$1".
Vielleicht deswegen? Was steht in $1?
 
Hi,

nee, das ist schon OK.
Die Variable FILE ist unabhängig von BPM.
in $1 steht der Pfad zur zu spielenden Musikdatei, in $2 optional die BPM. Beispielsweise:
Code:
music ./deckthehalls.mus 110
 
Hi Schard,

ändere doch einfach mal die play()-Funktion in der ersten Version wie folgt:
Code:
play() {
        FILE="$1"

        while read LINE; do
                # if (lineOK "$LINE"); then
                if lineOK "$LINE" ; then
                        echo "BPM=$BPM"
                        play_note $LINE
                fi
        done < $FILE
}

Innerhalb von Klammern führt die Bash Kommandos (im Beispiel also lineOK) in einer Subshell aus; Variablen, die du dort setzt, gelten natürlich nur lokal darin, und werden nicht an die Parent-Shell zurückgegeben.

Gruss,
A.
 
Hi floyd,

genau das war das Problem. Dass das Kommando dann in einer Subshell ausgeführt würde wusste ich nicht. Wieder etwas gelernt.

Beste Grüße

Schard
 

Ähnliche Themen

Switche abfragen über Script

script sshpass

Verschlüsseltes Backup-Script mit rsync

sed in awk

CentOS 5.8 –SQL Abfrage– HTML wird generiert und daraus müssen mehrere Mails versendet werden

Zurück
Oben