PLEAC examples - 1. Strings
1.0. Introduction
PicoLisp has no special string type. Instead, symbols are used. Syntactically, "transient" symbols resemble strings in other languages. Also, there is no separate character type. Instead, characters are represented by strings of length 1 (using 1 .. 3 bytes (UTF-8)).1.0.1. The Newline character
: (setq String "^J") -> "^J"References setq
1.0.2. The Escape character
: (setq String "^[") -> "^["References setq
1.0.3. Literal strings go in double quotes
: "Jon Maddog Orwant" -> "Jon Maddog Orwant"
1.0.4. Single quotes
Single quotes don't delimit strings and are not special inside strings: "This is a ' single quote!" -> "This is a ' single quote!"
1.0.5. Multiline strings
: "This is a multiline string containing a newline" -> "This is a multiline string^Jcontaining a newline" : "This is a multiline string \ without a newline" -> "This is a multiline string without a newline"
1.1. Accessing substrings
You want to access or modify just a portion of a string, not the whole thing. For instance, you've read a fixed-width record and want to extract the individual fields.1.1.1. Example
First 'chop' the string to convert it to a list of characters, and then use the rich set of list processing functions. Optionally, you can 'pack' the result to a string (not necessary in many cases, as many functions that expect a string also accept a list of characters).
: (let S (chop "This is a suitable string")
(prinl (cut 5 'S))
(cut 3 'S)
(prinl (cut 8 'S))
(prinl (cut 8 'S))
(prinl S) )
This
a suitab
le strin
g
-> ("g")
References
chop
cut
let
prinl
1.1.2. Split at five byte boundaries
: (make (for (S (chop "This is what you have") S)
(link (pack (cut 5 'S))) ) )
-> ("This " "is wh" "at yo" "u hav" "e")
References
chop
cut
for
link
make
pack
1.1.3. Usage of 'car', 'head' and 'tail' to get a substring
: (let S (chop "This is what you have")
(prinl (car S))
(prinl (tail 2 (head 4 S)))
(prinl (tail -13 S))
(prinl (tail 1 S))
(prinl (tail 4 S))
(prinl (head 3 (tail 8 S))) )
T
is
you have
e
have
you
-> ("y" "o" "u")
References
car
chop
head
let
prinl
tail
1.1.4. Test for substrings with 'pre?' and 'sub?'
: (pre? "a" "abc") -> "abc" : (sub? "bc" "abcdef") -> "abcdef" : (sub? "x" "abc") -> NILReferences pre? sub?
1.1.5. Use the 'match' function
: (match '("a" "b" @X "d" "e") (chop "abcde"))
-> T
: @X
-> ("c")
Note: the '@' character is a 'wildcard" used by 'match'.References chop match pat?
1.1.6. Substitute "at" for "is", restricted to first five characters
: (match '(@A "i" "s" @Z) (head 5 (chop "Me is You"))) (pack @A "at" @Z) -> "Me at"Note: the '@' character is a 'wildcard" used by 'match'.
References chop head match pack pat?
1.1.7. Exchange the first and last letters in a string
: (let S (chop "make a hat")
(xchg S (tail 1 S))
(pack S) )
-> "take a ham"
References
chop
let
pack
tail
xchg
1.1.8. Extract column
: (pack (tail 6 (head 12 (chop "To be or not to be")))) -> "or not"References chop head pack tail
1.1.9. Skip every second character
: (pack (filter prog2 (chop "To be or not to be") '(T NIL .))) -> "T eo o ob"References chop filter pack prog2
1.1.10. Defining a sub-string function: A silly/fun exercise
Before we get to the definitions, here are some usage examples.: (substring "Hello, world" 8) -> "world" : (substring "Hello, world" 8 3) -> "wor"First attempt at a definition.
(de substring (Str Start Len)
(pack
(head
(or Len (length Str))
(nth (chop Str) Start) ) ) )
References
pack
head
length
nth
chopAfter consulting with abu, who mentioned that head and length are expensive and should be avoided if possible (to make the function more performant), here is another attempt (mostly abu's ideas: e.g., the use of con).
(de substring (Str Start Len)
(let L (nth (chop Str) Start)
(and Len (con (nth L Len)))
(pack L) ) )
References
pack
nth
chop
con
1.2. Establishing a Default Value
You would like to give a default value to a scalar variable, but only if it doesn't already have one. It often happens that you want a hard-coded default value for a variable that can be overridden from the command-line or through an environment variable.1.2.1. Use B if B is true, else C
: (setq B NIL) -> NIL : (setq C NIL) -> NIL : (setq A (or B C)) -> NIL : (setq B T) -> T : (setq A (or B C)) -> TReferences or setq
1.2.2. Set X to Y unless X is already true
: X -> NIL : Y -> NIL : (setq Y 42) -> 42 : (default X Y) -> 42 : X -> 42 : (setq Y 11) -> 11 : (default X Y) -> 42 : X -> 42References default setq
1.2.3. Use function B if it is a valid function, else use C
: B -> NIL : C -> NIL : (setq A (or (fun? B) C)) -> NIL # The value of C, because B is not a valid function : (de B (x) (println x)) -> B : (de C (y) (println y)) -> C : (setq A (or (fun? B) C)) -> (x) # Argument list of B, because it is a valid function : A -> (x) : (setq B NIL) -> NIL : (setq A (or (fun? B) C)) -> ((y) (println y)) : A -> ((y) (println y)) # Value of C, since B is not a valid function : (def 'A (or (fun? B) C)) -> A : A -> ((y) (println y)) # Value of C, since B is not a valid functionReferences de def fun? or println setq
1.2.4. Use a value if (an) argument(s) is/are specified to the script
: (opt) -> NIL : (setq Dir (or (opt) "/tmp")) -> "/tmp" : Dir -> "/tmp" : (setq Dir (if (argv) (car @) "/tmp")) -> "/tmp" : Dir -> "/tmp"References argv car if opt or setq
1.2.5. Find the user name on Unix systems, depending on values
: (sys "USER")
-> "arie"
: (sys "LOGNAME")
-> "arie"
: (native "@" "getlogin" 'S)
-> NIL
: (car (native "@" "getpwuid" '(S) UserID))
-> NIL
: (setq User
(or
(sys "USER")
(sys "LOGNAME")
(native "@" "getlogin" 'S) # 'native' only in 64-bits
(car (native "@" "getpwuid" '(S) UserID))
(pack "Unknown uid number " UserID) ) )
-> "arie"
References
car
native
or
pack
setq
sys
1.2.6. Use defaults for uninitialized function parameters
: (de foo (A B)
(default A 1 B 2)
(list A B) )
-> foo
: (foo)
-> (1 2)
: (foo NIL NIL)
-> (1 2)
: (foo 11)
-> (11 2)
: (foo 11 NIL)
-> (11 2)
: (foo NIL 12)
-> (1 12)
: (foo 11 12)
-> (11 12)
References
de
default
list
1.2.7. Bind value depending on "empty" or NIL status of a variable
: B -> NIL : C -> NIL : (setq A (if B B C)) -> NIL : A -> NIL : (setq B 100) -> 100 : (setq A (if B B C)) -> 100 : A -> 100 : (setq B NIL) -> NIL : (setq C 300) -> 300 : (setq A (if B B C)) -> 300 : A -> 300References if setq
1.3. Exchange values without using temporary variables
You want to exchange the values of two scalar variables, but don't want to use a temporary variable.1.3.1. Using the 'xchg' function
: (setq Var1 "first") -> "first" : (setq Var2 "second") -> "second" : (xchg 'Var1 'Var2) -> "first" : Var1 -> "second" : Var2 -> "first"References setq xchg
1.3.2. Using 'setq' (now we need a temporary variable)
: (setq A "first") -> "first" : (setq B "second") -> "second" : (setq Temp A A B B Temp) -> "first" : Temp -> "first" : A -> "second" : B -> "first"References setq
1.4. Converting Between ASCII Characters and Values
You want to print out the number represented by a given ASCII character, or you want to print out an ASCII character given a number.1.4.1. Simple conversion
: (char "x") -> 120 : (char 120) -> "x"References char
1.4.2. Convert a string of characters
: (mapcar char (chop "sample"))
-> (115 97 109 112 108 101)
: (pack (mapcar char (115 97 109 112 108 101)))
-> "sample"
# Remember the movie "Space Odyssee"?
: (pack
(mapcar
'((C) (char (inc (char C))))
(chop "HAL") ) )
-> "IBM"
References
char
chop
inc
mapcar
pack
1.5. Processing a String One Character at a Time
You want to process a string one character at a time.1.5.1. Iterate over a string
: (setq S "google")
-> "google"
: (for Char (chop S)
(println Char))
"g"
"o"
"o"
"g"
"l"
"e"
-> "e"
References
chop
for
println
setq
1.5.2. Find unique chars in a string
: (prinl "unique chars are: " (sort (uniq (chop "an apple a day"))))
unique chars are: adelnpy
-> (" " "a" "d" "e" "l" "n" "p" "y")
: (let Seen NIL
(for C (chop "an apple a day")
(accu 'Seen C 1) )
(pack (sort (mapcar car Seen))) )
-> " adelnpy"
References
accu
car
chop
for
let
mapcar
pack
prinl
sort
uniq
1.5.3. Total ASCII value of a string
: (sum char (chop "an apple a day")) -> 1248References char chop sum
1.5.4. Compute 16-bit checksum of all input files
Store the script below in a script file named "sum":
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
# sum - compute 16-bit checksum of all input files
(let Sum 0
(while (opt)
(in @
(while (char) (inc 'Sum (char @))) ) )
(println (% Sum 65535)) )
(bye)
Then execute the following commands in the shell:
chmod 777 sum ./sum /usr/lib/picolisp/lib.l /usr/share/picolisp/lib/misc.lThis sums the ASCII values of all characters in the 2 files "lib.l" and "misc.l". The outcome may vary, because PicoLisp is actively being updated!
References bye char in inc let opt println while
1.5.5. Emulate a slow line printer
Store the script below in a script file named "slowcat":
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
# slowcat - emulate a s l o w line printer
# usage: slowcat [-DELAY] [files ...]
(let Delay (ifn (lt0 (format (car (argv)))) 1 (opt) (- @))
(for F (argv)
(for C (in F (till))
(prin C)
(wait (* 30 Delay)) ) ) )
(bye)
Then execute the following commands in the shell:
chmod 777 slowcat ./slowcat /usr/lib/picolisp/lib.l /usr/share/picolisp/lib/misc.lThis *slowly* prints the files "lib.l" and "misc.l". Note: you always can use Ctrl-c :-)
References * argv car for format ifn in let lt0 opt prin till wait
1.6. Reversing a String by Word or Character
You want to reverse the characters or words of a string.1.6.1. Example
(setq RevChars (flip (chop String)) RevWords (glue " " (flip (split (chop String) " "))) )References chop flip glue setq split
1.6.2. Reverse word order
: (glue " "
(flip
(split (chop "Yoda said, "can you see this?"") " ") ) )
-> "this?" see you "can said, Yoda"
References
chop
flip
glue
split
1.6.3. Check if a word is a valid palindrome
: (de palindrome? (S)
(= (setq S (chop S)) (reverse S)) )
-> palindrome?
: (palindrome? "reviver")
-> T
# The longest Dutch palindrome I know of ... :)
: (palindrome? "nelliplaatstopnparterretrapnpotstaalpillen")
-> T
References
=
chop
de
reverse
setq
1.6.4. Fetch palindromes from file (skip lines < 5 characters
Create the example file pfiletest (source):abc asantadoglivedasadevilgodatnasa peep amenicycinema level godlivesevildog madamenotonemanisselflessInamenotonemadamUse it for the example:
: (in "pfiletest"
(until (eof)
(let L (line)
(and
(> (length L) 5)
(= L (reverse L))
(prinl L) ) ) ) )
asantadoglivedasadevilgodatnasa
amenicycinema
godlivesevildog
-> NIL
References
=
>
and
eof
in
length
let
line
prinl
reverse
until
1.7. Expanding and Compressing Tabs
You want to convert tabs in a string to the appropriate number of spaces, or vice versa. Converting spaces into tabs can be used to reduce file size when the file has many consecutive spaces. Converting tabs into spaces may be required when producing output for devices that don't understand tabs or think they're at different positions than you do.1.7.1. Expand tabs
Note that the 'line' function reads a line from the current input channel. In this case that is STDIN.
: (let Str (line)
(use (@A @Z)
(while (match '(@A "^I" @Z) Str)
(setq Str
(conc
@A
(need (- 8 (% (length @A) 8)) " ")
@Z ) ) ) )
Str )
a b c
-> (" " " " " " "a" " " " " " " " " "b" " " " " " " " " "c")
References
-
%
conc
let
line
match
need
setq
use
while
1.7.2. Compress tabs
: (let Str (line)
(make
(while (nth Str 9)
(let S (trim (cut 8 'Str))
(chain S)
(or (= 8 (length S)) (link "^I")) ) )
(and Str (chain @)) ) )
a b c
-> ("^I" "a" "^I" "b" "^I" "c")
References
=
and
chain
cut
length
let
line
link
make
or
trim
while
1.8. Expanding Variables in User Input
You've read in a string like "You owe $debt to me" and you want to replace $debt in the string with the value of a variable named '$debt'.1.8.1. Using 'prinl' or 'pack'
: (let Dept 123
(prinl "You owe " Dept " to me.")
(pack "You owe " Dept " to me.") )
You owe 123 to me.
-> "You owe 123 to me."
References
let
pack
prinl
1.8.2. Using 'text'
: (text "I am @1 high and @2 long" 24 80) -> "I am 24 high and 80 long"References text
1.8.3. Using 'fill'
: (let (@Rows 24 @Cols 80)
(fill '(I am @Rows high and @Cols long)) )
-> (I am 24 high and 80 long)
References
fill
let
1.8.4. With as extra a check for uninitialized variables
: (let (@Rows 24 Lst '(I am @Rows high and @Cols long))
(for Var (fish pat? Lst)
(unless (val Var)
(set Var (pack "[NO VARIABLE: " Var "]")) ) )
(fill Lst) )
-> (I am 24 high and "[NO VARIABLE: @Cols]" long)
References
fill
fish
for
let
pack
pat?
set
unless
1.9. Controlling Case
A string in uppercase needs converting to lowercase, or vice versa.1.9.1. Example
: (uppc "bo peep") -> "BO PEEP" : (lowc "JOHN") -> "john"References lowc uppc
1.9.2. Make first letter of string uppercase
: (let S (chop "dromedary") (pack (uppc (car S)) (cdr S))) -> "Dromedary"References car cdr chop let pack uppc
1.9.3. Make first letter of each word uppercase and the rest lowercase
: (let Str "thIS is a loNG liNE"
(glue " "
(mapcar
'((W) (cons (uppc (car W)) (mapcar lowc (cdr W))))
(split (chop Str) " ") ) ) )
-> "This Is A Long Line"
References
car
cdr
chop
cons
glue
let
lowc
mapcar
split
uppc
1.9.4. Compare two strings ignoring their case
: (setq A "Elephant")
-> "Elephant"
: (setq B "ElEpHaNt")
-> "ElEpHaNt"
: (when (= (uppc A) (uppc B))
(prinl "A and B are the same") )
A and B are the same
-> "A and B are the same"
References
=
prinl
setq
uppc
when
1.9.5. Randowmly capitalize 20% of the letters in a file
Create the example file 'captest':Curtains forcing their will against the wind, children sleep, exchanging dreams with seraphim. The city drags itself awake on subway straps; and I, an alarm, awake as a rumor of war, lie stretching into dawn, unasked and unheeded. -- Poem by Maya AngelouUse it for the example:
: (in "captest"
(while (char)
(let C @
(prin (if (=0 (rand 0 4)) (uppc C) C)) ) ) )
CurtaiNs fOrcing their will
aGAINST the wiNd,
chilDreN sleep,
Exchanging drEAms wiTh
serAphim. The city
drags itseLf awake on
sUbwAy strAPs; and
I, an alarM, awAke as a
rumor of war,
lIE strEtching iNto dawn,
unasked and UnheEded.
-- PoeM by Maya AngeloU
-> "^J"
References
=0
if
in
let
prin
rand
uppc
while
1.10. Interpolating Functions and Expressions
You want a function call or expression to expand within a string. This lets you construct more complex templates than with simple scalar variable interpolation.1.10.1. Using 'prinl' and 'pack'
: (let N 7
(prinl "I have " (+ N 2) " guanacos.")
(pack "I have " (+ N 2) " guanacos.") )
I have 9 guanacos.
-> "I have 9 guanacos."
References
+
let
pack
prinl
1.10.2. Using 'text'
: (let N 7
(text "I have @1 guanacos." (+ N 2)) )
-> "I have 9 guanacos."
References
+
let
text
1.11. Indenting Here Documents
When using the multiline quoting mechanism called a here document, the text must be flush against the margin, which looks out of place in the code. You would like to indent the here document text in the code, but not have the indentation appear in the final string value.1.11.1. Using our own function definition
: (de myhere (Target) # The built-in 'here' cannot be used
(char)
(setq Target (chop Target))
(make
(for (L (line) (and L (<> L Target)) (line))
(link L) ) ) )
-> myhere
# In one step ...
: (setq Var (mapcar clip (myhere "HERE_TARGET")))
line 1
line 2
line 3
HERE_TARGET
-> (("i" "n" "e" " " "1") ("l" "i" "n" "e" " " "2") ("l" "i" "n" "e" " " "3"))
# In two steps ...
# Step 1
: (setq Var (myhere "HERE_TARGET"))
line 1
line 2
line 3
HERE_TARGET
-> (("i" "n" "e" " " "1") ("l" "i" "n" "e" " " "2") ("l" "i" "n" "e" " " "3"))
# Step 2
: (setq Var (mapcar clip Var))
-> (("i" "n" "e" " " "1") ("l" "i" "n" "e" " " "2") ("l" "i" "n" "e" " " "3"))
References
<>
and
char
chop
clip
de
for
line
link
make
mapcar
setq
1.11.2. Echo the poem until end of doc
: (let (Str (prog (char) (line)) Cnt 1)
(for (S Str (and S (sp? (car S))) (cdr S))
(inc 'Cnt) )
(loop
(prinl (nth Str Cnt))
(T (eof))
(setq Str (line))
(T (= '`(chop "EVER_ON_AND_ON") Str)) ) )
Now far ahead the Road has gone,
Now far ahead the Road has gone,
And I must follow, if I can,
And I must follow, if I can,
Pursuing it with eager feet,
Pursuing it with eager feet,
Until it joins some larger way
Until it joins some larger way
Where many paths and errands meet.
Where many paths and errands meet.
And whither then? I cannot say.
And whither then? I cannot say.
--Bilbo in /usr/src/perl/pp_ctl.c
--Bilbo in /usr/src/perl/pp_ctl.c
EVER_ON_AND_ON
-> NIL
References
=
and
car
cdr
char
chop
eof
for
inc
let
line
loop
prinl
prog
sp?
1.12. Reformatting Paragraphs
Your string is too big to fit the screen, and you want to break it up into lines of words, without splitting a word between lines. For instance, a style correction script might read a text file a paragraph at a time, replacing bad phrases with good ones. Replacing a phrase like utilizes the inherent functionality of with uses will change the length of lines, so it must somehow reformat the paragraphs when they're output.1.12.1. Example
: (let Input
(chop
(wrap 17
(conc (need 4 " ")
(chop
"Folding and splicing is the work of an editor,
not a mere collection of silicon
and
mobile electrons!" ) ) ) )
(prinl (replace Input "^J" "^J ")) )
Folding and
splicing is the
work of an
editor, not a
mere collection
of silicon and
mobile electrons!
-> (" " " " " " " " "F" "o" "l" "d" "i" "n" "g" " " "a" "n" "d" "^J " "s" "p" "l" "i" "c" "i" "n" "g" " " "i" "s" " " "t" "h" "e" "^J " "w" "o" "r" "k" " " "o" "f" " " "a" "n" "^J " "e" "d" "i" "t" "o" "r" "," " " "n" "o" "t" " " "a" "^J " "m" "e" "r" "e" " " "c" "o" "l" "l" "e" "c" "t" "i" "o" "n" "^J " "o" "f" " " "s" "i" "l" "i" "c" "o" "n" " " "a" "n" "d" "^J " "m" "o" "b" "i" "l" "e" " " "e" "l" "e" "c" "t" "r" "o" "n" "s" "!")
References
chop
conc
let
need
prinl
replace
wrap
1.13. Escaping Characters
You need to output a string with certain characters (quotes, commas, etc.) escaped. For instance, you're producing a format string for sprintf and want to convert literal % signs into %%.1.13.1. Add in front of characters in Str that are also in CharList
: (let (CharList '(a d g) Str "abcdefghi")
(pack
(mapcar
'((C) (pack (and (member C CharList) "\") C))
(chop Str) ) ) )
-> "\abc\def\ghi"
References
and
chop
let
mapcar
member
pack
1.13.2. Duplicate each character in Str that is also present in Charlist
: (let (CharList '(a d g) Str "abcdefghi")
(pack
(mapcar
'((C) (pack (and (member C CharList) C) C))
(chop Str) ) ) )
-> "aabcddefgghi"
References
and
chop
let
mapcar
member
pack
1.14. Trimming Blanks from the End of a String
You have read a string that may have leading or trailing whitespace, and you want to remove it.1.14.1. Remove trailing whitespace
: (setq String " abcde ")
-> " abcde "
: (trim (chop String))
-> (" " " " "a" "b" "c" "d" "e")
References
chop
setq
trim
1.14.2. Echo the typed input between > and <
: (in NIL
(until (eof)
(prinl ">" (clip (line)) "<") ) )
abc
>abc<
def
>def<
References
clip
in
eof
line
prinl
until
1.15. Parsing Comma-Separated Data
You have a data file containing comma-separated values that you need to read in, but these data fields may have quoted commas or escaped quotes in them.Most spreadsheets and database programs use comma-separated values as a common interchange format.
1.15.1. Example
: (for (I . Line)
(let *Uni T
(str
"XYZZY,"","O'Reilly, Inc","Wall, Larry","a
\"glug\" bit,",5, "Error, Core Dumped"" ) )
(prinl I " : " Line) )
1 : XYZZY
2 :
3 : O'Reilly, Inc
4 : Wall, Larry
5 : a "glug" bit,
6 : 5
7 : Error, Core Dumped
-> "Error, Core Dumped"
References
for
let
prinl
str
1.16. Soundex Matching
You have two English surnames and want to know whether they sound somewhat similar, regardless of spelling.This would let you offer users a "fuzzy search" of names in a telephone book or with a search engine like Google, to catch "Smith" and "Smythe" and others within the set, such as "Smite" and "Smote."
Note that the soundex algoritm differs for each human language!
Note that PicoLisp also has a builtin soundex function (ext:snx). But here another version is shown.
1.16.1. Example
: (de soundex (Str)
(pack
(pad -4
(cons
(uppc (char (char Str)))
(head 3
(let Last NIL
(extract
'((C)
(and
(setq C
(case (uppc C)
(`(chop "BFPV") "1")
(`(chop "CGJKQSXZ") "2")
(("D" "T") "3")
("L" "4")
(("M" "N") "5")
("R" "6") ) )
(<> Last C)
(setq Last C) ) )
(cdr (chop Str)) ) ) ) ) ) ) )
-> soundex
# Check soundex for a few similar sounding strings
: (soundex "Hello World")
-> "H464"
: (soundex "Hallo World")
-> "H464"
: (soundex "Smith")
-> "S530"
: (soundex "Smithe")
-> "S530"
: (soundex "Smyithe")
-> "S530"
# The following example calls the native Linux function 'getenv'
# in order to fetch the hostname from it (env variable = NAME).
# Then it reads user input (a guess for the hostname) in this case 'hp-erie'.
# Then it shows if it is a Soundex match or not!
: (flush)
-> T
: (let (InHostname (clip (in NIL (line T))) InHostnameSoundex (soundex InHostname))
(println "InHostname:" InHostname " InHostnameSoundex:" InHostnameSoundex)
(when (native "@" "getenv" 'S "NAME")
(let (EnvHostname @ EnvHostnameSoundex (soundex EnvHostname))
(if (= InHostnameSoundex EnvHostnameSoundex)
(println "MATCH!!!: EnvHostname:" EnvHostname "EnvHostnameSoundex:" EnvHostnameSoundex)
(println "NO MATCH: EnvHostname:" EnvHostname "EnvHostnameSoundex:" EnvHostnameSoundex)))))
hp-erie
"InHostname:" "hp-erie" " InHostnameSoundex:" "H160"
"MATCH!!!: EnvHostname:" "HP-Arie" "EnvHostnameSoundex:" "H160"
-> "H160"
Note: (sys "NAME") == (native "@" "getenv" 'S "NAME")References <> and case cdr char chop cons de extract head let pack pad setq uppc
1.17. Fix spelling of words in a file given a map (here called Data)
Words are often written in a wrong way. Here we show a word together with its correct spelling.1.17.1. Example
First create the following script and name it 'fixstyle'.
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
# Use: ./fixstyle [-v]
(and (= "-v" (opt)) (on *Verbose))
(de Data
("analysed" . "analyzed")
("built-in" . "builtin")
("chastized" . "chastised")
("commandline" . "command-line")
("de-allocate" . "deallocate")
("dropin" . "drop-in")
("hardcode" . "hard-code")
("meta-data" . "metadata")
("multicharacter" . "multi-character")
("multiway" . "multi-way")
("non-empty" . "nonempty")
("non-profit" . "nonprofit")
("non-trappable" . "nontrappable")
("pre-define" . "predefine")
("preextend" . "pre-extend")
("re-compiling" . "recompiling")
("reenter" . "re-enter")
("turnkey" . "turn-key") )
(in NIL
(while (apply echo '`(mapcar car Data))
(let (Key @ Val (get Data Key))
(when *Verbose
(out 2 (prinl Key " => " Val)) )
(prin Val) ) ) )
(bye)
Then execute the following in the Linux shell:
chmod 777 fixstyle ./fixstyleThe program waits for input. Enter a few words, also some in the Data list above on the left side, e.g.:
hello reenter trash pre-define exitAlso try in the shell:
./fixstyle -vand see what happens!
References = and apply bye car de echo get in let mapcar on opt out prin prinl when while
1.18. Use Lisp expressions to 'grep' lines from output of Linux 'ps' command
Create a program which extract specific lines of the output of the Linux command 'ps', which shows Linux processes.1.18.1. Example
First create the following script and name it 'psgrep'.
#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
#
# Use: psgrep 'lisp-expression'
#
# Takes a single optional argument:
# An arbitrary lisp expression without the outermost parentheses
#
# For example:
# psgrep '= "Ss+" STAT'
# psgrep 'and (> SIZE 10000) (= TT "tty1")'
# psgrep 'member UID (101 102 104 106)'
#
# The variables (case-sensitive!) have the
# same names as the column headers
(load "@lib/misc.l")
(de PsFields
(F 1 "flags" NIL (read))
(UID 6 "uid" NIL (read))
(PID 6 "pid" NIL (read))
(PPID 6 "ppid" NIL (read))
(PRI 4 "pri" NIL (read))
(NI 4 "nice" NIL (read))
(NIL 1)
(SIZE 5 "size" NIL (read))
(NIL 1)
(RSS 5 "rss" NIL (read))
(NIL 1)
(WCHAN -7 "wchan" NIL (skip) (till " " T))
(STAT -5 "stat" NIL (skip) (till " " T))
(TT -9 "tty" NIL (skip) (till " " T))
(TIME 8 "time" (tim$ TIME T) (skip) ($tim (till " " T)))
(NIL 1)
(COMMAND -30 "command" NIL (char) (line T)) )
(let Cond (or (str (opt)) T)
(in (list 'ps "hax" "-o" (glue "," (extract caddr PsFields)))
(let Fmt (mapcar cadr PsFields)
(apply tab (mapcar car PsFields) Fmt)
(bind (mapcar car PsFields)
(until (eof)
(for Fld PsFields
(when (car Fld)
(set @ (run (cddddr Fld))) ) )
(when (eval Cond)
(apply tab
(mapcar
'((Fld) (or (eval (cadddr Fld)) (val (car Fld))))
PsFields )
Fmt ) ) ) ) ) ) )
(bye)
Then execute the following commands in the Linux shell:
chmod 777 psgrep psgrep '= "Ss+" STAT' psgrep 'and (> SIZE 10000) (= TT "tty1")' psgrep 'member UID (101 102 104 106)'Note: results on Windows WSL are not valid.
References apply bind bye cadddr caddr cadr car cddddr cond de eof eval extract for glue in let list load mapcar opt or run set str tab until val when
http://picolisp.com/wiki/?pcepleacstrings
| 19nov18 | rick |
