Hur få sträng att bli lista vid läsning av fil?

Tråden skapades och har fått 6 svar. Det senaste inlägget skrevs .
1
  • Medlem
  • 2011-06-09 10:08

Jag läser in text från en textfil (read file min_textfil.txt) och vill att raden
{{42, 80, 7}, {84, 122, 7}, {126, 164, 7}, {168, 206, 7}, {210, 248, 7}}
ska läsas in som ett objekt i en lista. Men när jag läser filen blir det en sträng, dvs
"{{42, 80, 7}, {84, 122, 7}, {126, 164, 7}, {168, 206, 7}, {210, 248, 7}}"
Hur får jag denna sträng att bli en post i en lista, se dump:

  • Medlem
  • 2011-06-09 22:00

Verkar inte gå att göra med read file...

Hade det varit en "platt" lista och om strängen hade varit utan krullparenteser, alltså:
"42, 80, 7, 84, 122, 7, 126, 164, 7, 168, 206, 7, 210, 248, 7"

så skulle det gå att läsa in den som en lista med:
set theResult to read file min_textfil.txt as integer using delimiter ","

  • Medlem
  • 2011-06-09 22:12

Jag kan bestämma hur textfilen ska se ut, men jag måste gruppera precis som i exemplet. Jag kan leva utan de yttersta måsvingarna men inte utan de inre (om det inte finns något annat sätt att lösa det.
Jag vet inte i förväg hur många items varje liten lista (de inre måsvingarna) innehåller. Den lilla listan kan också innehålla text.

Prova att köra med två olika delimeters, t,ex, komma inne i listorna och semikolon mellan dem. Första vändan skapar du en templist med med sammansatta strängar, andra vändan loopar du genom templist, typ for i = 1 to nitems(list1) och använder då den inre avgränsaren som då borde resultera i de n listor du vill ha. Tyvärr kan jag inte hjälpa dig med syntaxen i just AS.:(

Det du vill göra är en vanlig förfrågan i många programmeringsspråk, att ta en text och köra den genom kompileraren så att det blir kod, istället för text, alternativt att du vill exekvera texten som ett stycke kod och få resultatet av koden. I andra språk brukar det heta saker som "eval", "exec" etc.

I AppleScript kan du antingen använda OSAcompile (via do shell) men det du vanligtvis vill göra är att använda det kommando som finns via Standard Additions, "run script", som tar din text, kompilerar det som kod, exekverar koden, och returnerar resultatet. Så här:

set myString to "{{42, 80, 7}, {84, 122, 7}, {126, 164, 7}, {168, 206, 7}, {210, 248, 7}}"

set myScriptResult to run script myString

return myScriptResult

I andra språk är man ytterst vaksam mot sån här dynamiskt laddad kod, för låt säga att din textsträng istället för en enkel lista innehöll skadlig kod.

Med andra ord, man ska vara ytterst, ytterst försiktig med att exponera den kod som ska exekveras, annars öppnar man ett säkerhetshål av gigantiska mått (bara fantasin sätter gränser för vad en illasinnad person kan göra med dynamiskt laddad kod i en process som körs med admin-rättigheter i ett nätverk)

Det sättet man gör det är, förutom att ta kontroll över vem/vad som får skriva input, att förhandsgranska koden som ska köras. Ett enkelt sätt i ditt fall vore att kontrollera att texten börjar och slutar med { eller } samt att godkända tecken är siffror, mellanslag, komma och parenteser. Innehåller koden något annat så är det inte en giltig lista och ska inte köras. Mao vill du göra något i den här stilen:

set myString to "{{42, 80, 7}, {84, 122, 7}, {126, 164, 7}, {168, 206, 7}, {210, 248, 7}}"

if isList(myString) then
	set myScriptResult to run script myString
	return myScriptResult
else
	-- vad du vill göra när scriptet går fel
end if




on isList(codeString)
	-- Tecken som får finnas i din lista
	set myApprovedList to every character of "0123456789. ,"
	
	--Enkel kontroll för att se att inledande och avslutande sträng är de som krävs för en lista
	if (codeString does not start with "{") and (codeString does not end with "}") then
		return false
	end if
	
	--variabler för att kunna räkna antalet listseparatorer
	set myLeftBraces to {}
	set myRightBraces to {}
	
	repeat with i in codeString
		set myCurrentItem to contents of i
		
		if (myCurrentItem is "{") then
			set end of myLeftBraces to myCurrentItem
		else if (myCurrentItem is "}") then
			set end of myRightBraces to myCurrentItem
		else if (myCurrentItem is not in myApprovedList) then
			return false
		end if
	end repeat
	
	if (count myLeftBraces) ≠ (count of myRightBraces) then
		return false
	end if
	
	return true -- om alla tecken har klarat kontrollen utgår vi från att det är en lista och returnerar därför true
end isList
  • Medlem
  • 2011-06-10 09:15

Där satt den!

Ursprungligen av Baron:

Där satt den!

set myList to {83, 97, 32, 102, 108, 105, 99, 107, 97, 110, 33}
set myString to ""

repeat with i in myList
	set myString to myString & (ASCII character (contents of i))
end repeat

display dialog myString
1
Bevaka tråden