scheme 实现简单 grep 命令

目录

无意中发现了 chicken scheme 重燃了我学习 scheme 的兴趣。我一直想用 Lisp 作为自己的 shell 语言,无奈 clojure 启动太慢,newlisp 太过小众,
common lisp 编译后文件太大,这个想法就搁浅了,最后还是 Bash shell 用起来顺手。但是 chicken scheme 似乎解决了我面临的所有问题,首先如果
作为本地的脚本语言它有丰富的库还有极快的启动速度,其次你写的脚本可以编译成 native code 然后传到其他机器上运行,而且编译生成的文件比起
common lisp 小很多,这样可以让自己写的程序轻松的在其他机器上运行。下面就介绍一下如何实现一个简单的 grep 命令

程序

(use utils)
(use regex)
(use srfi-1)

(if (eq? '() (command-line-arguments))
  (begin
   (print "请输入文件名")
   (exit 1)
  )
  )
(define f (car (command-line-arguments)))
(define r (list-ref (command-line-arguments) 1))


(define (grep regex lst)
  (filter (lambda (x) (string-search regex x)) lst) )

(define (print-l lst)
  (filter (lambda (x) (print x)) lst)
  )


(with-input-from-file f
  (lambda () (let loop ((line (read-line)))
               (if (eof-object? line)
             0
       (begin
         (print-l (grep r (list line)))
                   (loop (read-line))
       )
       ))))

作为脚本运行

jimila@CDYJY-JINGML:testscheme$ csi -s mygrep.scm  test.txt '[1]{4}'
1111
11110
11111
11112
11113
11114
11115
11116
11117
11118
11119
21111
31111
41111
51111
61111
71111
81111
91111

编译程序

# 如果直接这样编译运行会报错
jimila@CDYJY-JINGML:testscheme$ csc -static mygrep.scm  -o mygrep
jimila@CDYJY-JINGML:testscheme$ ./mygrep test.txt '[12]{3}'

Error: (require) cannot load extension: regex

	Call history:

	read.scm:10: ##sys#require	  	<--

# 这个问题我也很疑惑,有些依赖的库在编译为静态文件的时候不会自动加进去,这时我们需要手动的把这些依赖编译进去,具体步骤如下。
chicken-install -retrieve regex
csc -unit regex -emit-import-library regex -c regex/regex.scm -o regex.o
csc -uses regex -c mygrep.scm -o mygrep.o
csc -static mygrep.o regex.o -o r

# 这样就得到了可以在其他同平台运行的 native code 了
# 只有 5.4M 对我来说已经非常小了,如果你见过 common lisp 编译后的大小
jimila@CDYJY-JINGML:testscheme$ du -sh mygrep 
5.4M	mygrep

jimila@CDYJY-JINGML:testscheme$ file mygrep 
mygrep: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=46d22d1d5974cea1607cece7e76e95dfe38c8822, not stripped

jimila@CDYJY-JINGML:testscheme$ ./mygrep test.txt '[1]{4}'
1111
11110
11111
11112
11113
11114
11115
11116
11117
11118
11119
21111
31111
41111
51111
61111
71111
81111
91111


目录