Raspbian Dialog checklist output uit bestand naar array

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Joen
  • Registratie: Juli 2003
  • Laatst online: 09-08 18:34
Ik leer elke dag weer een beetje bij op Linux/Debian/Raspbian gebied met mijn Raspberry Pi's en veel ontdek en leer ik wel door goed te zoeken op Google.

Ik ben nu bezig met mijn bash shell script te verfijnen om eenvoudig timelapses te kunnen maken.
Dialog vind ik tot nu toe het prettigste om daar voor te gebruiken hoewel het wel lastig is om input af te vangen. Die input afvangen doe ik via tijdelijk weggeschreven bestanden die ook direct weer verwijderd worden.

1 ding loop ik nu nogal op vast: de input van checklists uitlezen. Misschien is het wel erg basic op vast loop, maar ik zie door de bomen het bos niet meer.

Stel ik heb 5 regels in de checklist met de simpele namen:
[ ] Line 1 Choose this to use line 1
[ ] Line 2 Choose this to use line 2
[ ] Line 3 Choose this to use line 3
[ ] Line 4 Choose this to use line 4
[ ] Line 5 Choose this to use line 5

En ik die daar van alleen de bovenste 3 regels dan wordt er dit weggeschreven in een bestand (bijvoorbeeld file.txt):
code:
1
"Line 1" "Line 2" "Line 3"


Nu wil ik graag die 3 teksten in losse variabelen kunnen gebruiken om vergelijkingen mee te maken in mijn script en afhankelijk daar van acties uitvoeren.

Tot nu toe worden de arrays zodanig opgebouwd dat als ik ze uitlees een rijtje krijg als:
code:
1
2
3
4
5
6
"Line
1"
"Line
2"
"Line
3"


Terwijl ik het wil kunnen uitlezen als testarray[0] met "Line 1", testarray[1] met "Line 2" en testarray[2] met "Line 3" (uiteraard zonder quotes).

Ik kan natuurlijk overwegen om zonder spaties in de teksten te werken, maar ik wil ook graag weten of en hoe het kan inclusief de spaties.

De bronnen die ik tot nu toe geraadpleegd heb:En op Tweakers:Dit is mijn testscriptje tot dusver:
Bash:
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
#!/bin/bash

#testarray=`cat file.txt`
#echo -e "$testarray"

#declare -a testarray=($(grep -o '".*"' file.txt | sed 's/"//g'))
declare -a testarray=($(cat file.txt));
#declare -a testarray=(cat file.txt);

echo -e "Contents of array:"
echo -e ${testarray[@]}
echo -e " "
echo "Length of array:"
echo -e ${#testarray[@]}
echo " "
echo "Array loop:"

n=0;
for item in "${testarray[@]}"; do
    let  n=n+1;
    echo "$n: $item";
done

echo -e "== AWK test ==";
testarray2=`awk /".*"/ file.txt`
echo -e "${testarray[@]}";
echo "First array item: ${testarray[0]}";


Dus is er een manier om de complete teksten tussen quotes inclusief spaties in een array te krijgen of kan ik beter overstappen naar andere benamingen die geen spatie bevatten?

Acties:
  • 0 Henk 'm!

  • arie_papa
  • Registratie: Augustus 2008
  • Laatst online: 12-09 14:34

arie_papa

Running on Ubuntu

Werken escapes \ niet?

[code]
echo -e "Contents\ of\ array:"
[/code]


Je quote, dus in principe zijn escapes niet nodig.

[ Voor 30% gewijzigd door arie_papa op 16-10-2015 18:17 ]

Statistieken zijn als bikini's: wat ze tonen is erg suggestief, wat ze niet tonen is essentieel


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 14-09 21:52

Hero of Time

Moderator LNX

There is only one Legend

Laat ik nou net soortgelijks hebben gedaan, maar dan met whiptail ipv dialog (had geen zin om die apart te installeren :P). Even zoeken....

Edit:
Major bummer, kan m'n scripts niet meer vinden :-(

Hoe dan ook, als je het toch al wegschrijft naar een bestand, dan komen ze toch elk op een aparte regel terecht? Dan doe je gewoon via een read line het bestand opnieuw inlezen en maak je er een array van op die manier.

Ben even met wat anders bezig, maar zal daarna een PoC maken voor je, met whiptail als dialog substituut.


Edit2:
Nou, laten we er dan maar gelijk een array van maken:
declare -a antwoord=( $(whiptail --separate-output --checklist testlijst 10 45 5 regel1 "dit is de eerste regel" off regel2 "dit is de tweede regel" off regel3 "dit is de derde regel" off 3>&1 1>&2 2>&3) )


Of, voor wat meer leesbaarder, direct in script vorm:
Bash:
1
2
3
4
5
6
7
#!/bin/bash
antwoord=( $(whiptail --separate-output --title "Prachtig voorbeeld van Hero of Time" \
--checklist "geef de lijst een naam" 15 45 5 \
regel1 "dit is de eerste regel" off \
regel2 "dit is de tweede regel" off \
regel3 "dit is de derde regel" off \
3>&1 1>&2 2>&3) )

De redirect aan het einde is nodig omdat whiptail het standaard naar stderr stuurt. Door de boel te wisselen, kan het in een variabele gezet worden. Lees de man-page van whiptail voor meer informatie.

Extra noot, waar ik de tekst 'regel1', 'regel2' en 'regel3' heb, kan je in principe met tekst werken dat een spatie bevat, maar in de praktijk krijg je dan een array waar je anders mee moet werken, dus houd het bij enkele woorden.


Edit 3:
Heb wat last van droge ogen en heb daarom je vraag niet helemaal goed gelezen. We gaan even uit van een bestand met de volgende inhoud:
code:
1
2
3
regel 1
regel 2
regel 3

Dus spaties erin, wat jij ook hebt. Dan doe je het volgende:
Bash:
1
2
3
4
5
6
7
#!/bin/bash
i=0
while read line
do
    array[$i]="${line}"
    let i++
done < $1 # bovenstaand bestand wordt meegegeven als parameter aan dit script

De quotes en accolades zijn niet verplicht.


Edit 4:
Dit is gewoon te leuk om niet te onderzoeken, kom op, je was al zo ver, waarom kom je hier dan niet op?

Combineer de twee hierboven en je kan dit gebruiken, zodat je de boel niet eerst naar een bestand hoeft te schrijven en die weer uit moet lezen:
Bash:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
antwoord=$(whiptail --separate-output --title "Prachtig voorbeeld van Hero of Time" \
--checklist "Dit is een super lijst" 15 45 5 \
"regel 1" "dit is de eerste regel" on \
"regel 2" "dit is de tweede regel" on \
"regel 3" "dit is de derde regel" on \
3>&1 1>&2 2>&3)

i=0
while read line
do
    array[$i]=$line
    let i++ 
done <<< "$antwoord"

Het is geen rocket science. ;)

[ Voor 135% gewijzigd door Hero of Time op 16-10-2015 23:48 . Reden: Ja, ik blijf bezig :P ]

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Joen
  • Registratie: Juli 2003
  • Laatst online: 09-08 18:34
Aha. Meerdere ideetjes voor de checklist uit te lezen dus. Ik zal eens kijken of ik dit weekend wat er van kan uitproberen. :)

Ik probeerde redirects te vermijden van de uitvoer te vermijden, omdat ze 1) er voor mij nogal ingewikkeld uit zien en 2) er iets was met de manier waarop dialog de uitvoeren gebruikt en verkeerd afvangen van de uitvoeren de weergave zou kunnen verstoren.

In de bases was mijn vraag dus eigenlijk:
Hoe kan ik van 1 regel uit een bestand file.txt met als inhoud op die regel:
code:
1
"Line 1" "Line 2" "Line 3"

Een array maken die los geschreven zou kunnen worden gezien als:
Bash:
1
2
3
testarray[0]="Line 1";
testarray[1]="Line 2";
testarray[2]="Line 3";


De wetenschap hoe dit aan te pakken wil ik overigens niet alleen icm dialog gebruiken, maar misschien ook voor andere toekomstige scripts.

Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 14-09 21:52

Hero of Time

Moderator LNX

There is only one Legend

Je moet hoe dan ook de --separate-output gebruiken, zie de man-page daarvoor:
code:
1
2
--separate-output
       For checklist widgets, output result one line at a time, with no quoting.  This facilitates parsing by another program.


Welke andere redirects wil je vermeiden? We zien niet hoe je dialog gebruikt en in de man-page ervan raden ze ook af om --stdout te gebruiken. De file descriptors voor de verschillende uitvoer is niet zo heel moeilijk. 0 is stdin, 1 is stdout, 2 is stderr. Dialog en whiptail spugen standaard hun output naar stderr, maar dat afvangen kan wat problematisch zijn als er ook werkelijk een error voorkomt. Zie http://www.linuxnix.com/l...ptors-explained-examples/ voor een mooie uitleg hiervan hoe dat werkt en hoe je ze kan gebruiken. Wat ik met mijn whiptail doe, is in principe een extra descriptor maken en die gebruiken (als ik het zelf goed begrijp :P).

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Joen
  • Registratie: Juli 2003
  • Laatst online: 09-08 18:34
Die optie was ik wel tegengekomen, maar niet goed gelezen kom ik er nu achter. Maar dan moet ik nog wel ontdekken hoe ik een string op basis van de seperator kan opsplitsen naar een array.

Het linkje wat je geeft ga ik zeker even een keer lezen. :)

En een terechte vraag hoe ik dialog gebruik. Hier een stukje uit een script waarin ik het gebruik:
Bash:
1
2
3
4
5
6
7
8
9
10
11
12
13
function askWidth {
    dialog --backtitle "$programtitle" --title "Width of photo's" --ok-label "Confirm" --cancel-label "Main menu" --inputbox "Please enter the width of the photo's:" 10 40 "1280" 2> /tmp/RasPiLapse.tmp.$$
    _return=$?;
    #echo -e "Exitcode: $_return";
    #sleep 3;
    if [ $_return -eq 1 ]; then
        mainmenu;
    else
        imgWidth=`cat /tmp/RasPiLapse.tmp.$$`
        rm -f /tmp/RasPiLapse.tmp.$$    
        askHeight;
    fi
}




Edit 17-10-2015 16:18 uur:
Door de --separator-output parameter icm het laatste stukje of "Hero of time" heb ik een testscriptje kunnen schrijven wat doet wat ik wil:
Bash:
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
#!/bin/bash
programtitle="File to Array reader"

function SelectFile {
    dialog --backtitle "$programtitle" --title "Information" --msgbox "This scripts let you choose a file to read on the next screen and then output it contents line by line into an array. After that it prints its array to the console." 0 0;
    dialog --backtitle "$programtitle" --title "Select file" --ok-label "Use file" --cancel-label "Cancel" --fselect "./" 15 60 2> /tmp/arraytest.tmp.$$
    _return=$?;
    #echo -e "Exitcode: $_return";
    #sleep 5;
    if [ $_return -eq 1 ]; then
        exitscript;
        #sleep 3;
    else
        filepath=`cat /tmp/arraytest.tmp.$$`
        rm -f /tmp/arraytest.tmp.$$
        ReadToArray;
    fi
}

function ReadToArray {
    echo -e "Reading '$filepath'...";
    while read line
    do
        testarray[$i]=$line;
        let i++ ;
    done < "$filepath"
    echo -e "Done";
    echo -e "-----------";
    echo -e "Number of lines / items: ${#testarray[@]}";
    echo -e "-----------";
    echo -e "Contents of array:";
    echo -e " ";
    n=0;
    for item in "${testarray[@]}"; do
        let  n=n+1;
        echo "$n: $item";
    done
    exitscript;
}

function exitscript {
    echo -e "=============================";
    echo -e "End of script";
    echo -e "=============================";
}

SelectFile;

Ik denk dat het mij wel zal lukken om dit verder uit te bouwen naar wat ik er uiteindelijk mee wil kunnen doen. :)

[ Voor 49% gewijzigd door Joen op 17-10-2015 16:23 ]


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 14-09 21:52

Hero of Time

Moderator LNX

There is only one Legend

Ik baal echt dat ik m'n oude scripts niet meer kan vinden, ik had nog eens een heel whiptail script gemaakt om software te compileren dat bij m'n toenmalige werk werd ontwikkeld. Het controleerde je AD credentials, deed een svn checkout afhankelijk van de selectie en had een lijstje met versies/tags van svn evenals omgevingen waar 't heen moest. Ik geloof niet dat ik het alleen maar op een stick heb gezet, want een paar maanden terug ben ik een stick van 16 GB verloren. Echt klote.

Zoals een echte programmeur/beheerder heb je in je carrière een tijd dat je iets briljants maakt en later niet meer weet hoe je dat nou precies hebt gemaakt. Dit is er voor mij een van.

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Joen
  • Registratie: Juli 2003
  • Laatst online: 09-08 18:34
Herkenbaar. :)
Overkomt mij ook wel eens. :P
Pagina: 1