staging.inyokaproject.org

read-Kommando Rückgabewerte mit Parameter -t und -s

Status: Ungelöst | Ubuntu-Version: Ubuntu 16.04 (Xenial Xerus)
Antworten |

testinger

Anmeldungsdatum:
18. Januar 2018

Beiträge: Zähle...

Hallo, ich hab da (offensichtlich) mal eine Frage. Ich habe folgendes Programm geschrieben:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/bin/bash
read -p "Setze Länge: " r
read -p "Setze Breite: " a
declare -a p=()
declare -a q=()
declare longitude=$((a/2))

for (( y=0 ; y<r ; y++ ))
do

	input=$(read -t 1)
	if [ $(($input)) == $((0)) ]
		then longitude=$(($longitude+1))
		else longitude=$(($longitude-1))
	fi

	for (( x=1 ; x<a ; x++ ))
	do
	if [ $(($x)) == $(($longitude)) ]
		then echo -n -e " \033[32mx\033[0m"
		elif [ $(($x)) == $((q[$y])) ]
		then echo -n -e " \033[34mx\033[0m"
		else echo -n -e " \033[30mo\033[0m"
	fi
	done

	echo " $y"
done

exit

Das Ziel ist ein in der Befehlszeile nach unten laufender Plot, auf dem ein X sitzt, der durch die Pfeiltasten gesteuert werden kann. Mein Problem ist, dass ich irgendwie den read-Befehl nicht verstanden habe. So wie ich das verstehe gibt der mi dem parameter "-t 1" nach einer Sekunde entweder "0" bei einer Eingabe oder "1", bei keiner Eingabe zurück. Wenn ich das Programm aber starte, dann läuft das "x" abhänig davon, ob ich in der 14-nten Zeile "0" oder "1" nehme, egal was ich eingebe nach links oder rechts. So, als würde read immer 0 zurückgeben. Wieso ist das so, und wie macht man es weg? Wo ich dabei bin: Wie würde ich das machen, wenn ich möchte, dass obwohl ich etwas eingebe, nichts ausgegeben wird? bei read -s scheint read dann einfach gar nichts zurückzugeben?

Danke schonmal im vorraus!!

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Hi testinger,

zuerst mal herzlich willkommen hier auf dem Forum !

Du hast da eine merkwürdige Art zu programmieren ... mit nur wenigen, ungewöhnlichen befehlen, die Du dann sehr ausgiebig wiederholst. 🤓
So richtig praktisch ist das allerdings nicht, und ein paar komische Nebeneffekte kann das nebenbei auch noch liefern.
Guck zum Vergleich mal in unserem Skripting-Wiki, wie ein üblicher Programmierstil aussehen würde. 😉

Mich irritiert, warum Du außerdem überall $((Shell Arithmetik)) einsetzt. - bezweckst Du damit etwas Spezielles ?
Außerdem:

  • Der read-Befehl kann grundsätzlich in eine Variable schreiben. (auch in Zeile 11 !)
    Und er liest auch erst beim [Enter]. (es sei denn, Du änderst das mit der Option -n )

  • Hast Du mal geguckt, was die Pfeiltasten zurückgeben ? → das sind jeweils mehrere Bytes, die Du mit read auch nacheinander auslesen musst !

Überhaupt solltest Du vielleicht mal besser in Prosa verraten was Du vorhast, und uns nicht nur Deinen Code zum Raten vorwerfen.

Erzähl mal ...

track

p.s:
ein kleines Testskript, um nur erstmal die Tastenabfrage zu testen:

1
2
3
4
while true; do
    read -t1 -n1 x;
    echo "- $x -";
done

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Ein kleiner Kniff: Wenn man dem Script von aussen die Laenge und Breite übergibt, dann muss man nicht so umständlich starten, was gerade bei wiederholtem Testen nervt.

Daher kann man sagen laenge=$1;breite=$2 und der erste Wert wird die Länge, der zweite die Breite. Und wenn das Länge und Breite sind, dann nennt man sie auch so, und nicht a und r oder Paul und Paula.

Und wenn man Defaultwerte verwenden will, wie 20, 20 dann kann man das mit "laenge=${1:-20}" erreichen. Wenn der erste Parameter anders gesetzt ist nimmt das Programm das, sonst 20.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash
laenge=${1:-20}
breite=${2:-20}
longitude=$((breite/2))
# Die sollen wohl noch mit Leben gefüllt werden? 
declare -a p=()
declare -a q=()

for (( y = 0 ; y < laenge ; y++ ))
do
	read -t 1 -n 1 -s taste 
	if [ "$taste" == "d" ]
		then ((longitude+=1))
	elif [ "$taste" == "a" ]
		then ((longitude-=1))
	fi
	echo 
	for (( x=1 ; x < breite ; x++ ))
	do
		if [ $(($x)) == $(($longitude)) ]
			then 
				echo -n -e " \033[32mx\033[0m"
			elif [ $(($x)) == $((q[$y])) ]
			then 
				echo -n -e " \033[34mx\033[0m"
			else 
				echo -n -e " \033[30mo\033[0m"
		fi
	done

	echo -n " $y"
done

In read -t 1 -n 1 -s taste unterdrückt -s das lästige Feedback in der Shell, -n 1 nimmt nur ein Zeichen entgegen, und input habe ich durch taste ersetzt, wie track schon vorschlug. Da ich nicht weiß, wie man die Pfeiltasten verwenden könnte, habe ich stattdessen 'a' und 'd' verwendet. Da liegt normalerweise die linke Hand (kl. u. mittlerer Finger).

testinger

(Themenstarter)

Anmeldungsdatum:
18. Januar 2018

Beiträge: 2

Danke für die schnelle Antwort.

@Track: so richtig kann ich dir gar nicht sagen, was das wird... 😀 Ich bin ehrlich gesagt gar nicht so an programmierung interessiert, aber hab mich mal aus spaß, und weil mir alleine zuhause krankgeschrieben lw war, mit bash beschåftigt und skripte ein bisschen vor mich hin.

@unknown_user: danke. Mir ist vor circa 10' im matheunterricht dann auch aufgefallen, dass das input an der falschen stelle war.

Ich probiere das dann alles aus, wenn ich nach hause komme.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Ah - ok.

Dann würde ich Dir ausdrücklich noch einmal den Bash-Guide in unserem Wiki empfehlen, sozusagen als Geländer, damit Du nicht so oft stolperst ... 😀

Und zum Anfüttern: Du kannst ja mal ein Menü-Skript von mir angucken, das ich vor Zeiten geschrieben habe. (mit Pfeiltaste rauf und runter)
Und meine persönliche Linksammlung - das erspart dir vll. etwas Sucherei. (Klar, das ist jetzt schon etwas fortgeschrittener, aber Du musst ja nicht sofort alles können !)

LG, und viel Spass dabei,

track

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Da Du schon Escapesequenzen benutzt kommt Dir sicher diese Funktion entgegen, die den Cursor an Stelle ROW COLUMN (x y) setzt:

1
2
3
4
5
gotoXy () {
	x=$1
	y=$2 
	echo -e -n "["$y';'$x'H'
}

Row zählt von 1 oben, column auch von 1 links.

Ob das fancy Zeichen den Transfer in Deinen Editor übersteht ist ungewiss. Es ist mit keiner Taste verbunden und \0x1b.

Man kann damit ein solches, kleines Spielchen für die syslog-Datei, basierend auf Deinem Ansatz, erzeugen, damit die auch mal einen Wert hat:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/bin/bash
laenge=${1:-40}
breite=${2:-90}
declare -a p=()
declare -a q=()
longitude=$((breite/2))

declare -a row
noise () {
	row[0]="  "
	row[1]="  "
	row[2]="  "	
	for (( i=0; i < laenge; i++ ))
	do rownum=$((i+1))
		row[$((i+3))]="$(sed -r -n "$rownum{s/ /#/g;s/[a-zA-Z)(\!&>/_=]/./g;s/[0-3]//g;s/[4-6]/../g;s/[7-9]/..../g;s/\[/ /g;s/]//g;s/:/./g;s/^(.{$breite}).*/\1/p}" /var/log/syslog)"
	done 
	row[$((i+4))]="           e "
	row[$((i+5))]="           o "
	row[$((i+6))]="           f "
}
noise

gotoXy () {
	x=$1
	y=$2 
	echo -e -n "["$y';'$x'H'
}

# clear screen 
echo -e "[2J"

for (( y = 1 ; y <= laenge ; y++ ))
do
	read -t .25 -n 1 -s taste 
	if [ "$taste" == "d" ]
		then ((longitude+=1))
	elif [ "$taste" == "a" ]
		then ((longitude-=1))
	fi
	echo

	echo -e "${row[$y]}"
	gotoXy $longitude $y
	echo -e "\033[32mx\033[0m"
	for ((rest=y+1; rest < y + 5; rest++ ))
	do
		echo "${row[$rest]}"
	done
done

echo "DONE"

Allerdings malt mir das aus unbekannten Gründen noch ab und an eine Leerzeile auf den Schirm.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
...#....#..........#....#.......# ...........x...............#..#......# ...#...##......#.......#...
...#....#..........#....#.......# ..........x................#..#......# ...#...##.....#...#.#......
...#....#..........#....#.......# ..........x..............#..#......# ...#...##....#......#..#.....
...#....#..........#....#.......# ..........x..............#..#......# ...#...##....#...#.......#...
...#....#..........#....#.......# ..........x......#..#......# ...#...##......#.......#.............
...#....#..........#....#.......# .........x.......#..#......# ...#...##.....#...#.#........#.....# 
...#....#..........#....#.......# .........x...........#..#......# ...#...##....#......#..#.........
...#....#..........#....#.......# ........x..........#..#......# ...#...##....#...#.......#....#....
...#....#..........#....#.... ...........#x.....#...#.###..#.#..#...-.....#--......#................
...#....#..........#....#.......# .........x.......#..#......# ...#...##......#.......#.............
...#....#..........#....#.... ...........#.x....#....#.......#....#.....#..#......#...#...#......#..
...#....#..........#....#.......# ..........x........#..#......# ...#...##......#.......#...........
...#....#..........#....#.......# ..........x..........#..#......# ...#...##.....#...#.#........#...
...#....#..........#....#.......# ...........x.........#..#......# ...#...##....#......#..#.........
...#....#..........#....#.......# ...........x.......#..#......# ...#...##....#...#.......#....#....
...#....#..........#....#.... .......#......x...#.###....#-.#..........................-.......#..#.
...#....#..........#....#.......# .........x.......#..#......# ...#...##......#.......#.............
...#....#..........#....#.......# .........x.........#..#......# ...#...##.....#...#.#........#.....

Man würde noch eine Kollisionserkennung machen mit der X-Position und dem Index des Strings in der aktuellen Zeile.

Antworten |