脚本语言的多领域应用与特性解析
1. 脚本语言概述
脚本语言近年来发展迅速,这得益于网络的持续发展、开源社区的活力以及创建新脚本语言所需的相对较低投入。与传统编译语言如 Java 或 C# 不同,脚本语言能让单个有才华的设计师在一两年内创建出可用的实现。
新的脚本语言融合了许多创新的语言设计概念。例如,Ruby 具有统一的对象模型、真正的迭代器、数组切片等特性;Python 则提供了匿名一等函数和类似 Haskell 的列表推导式等功能。
2. 问题领域分类
脚本语言主要应用于多个明确的问题领域,下面将详细介绍这些领域。
3. shell(命令)语言
3.1 发展历程
早期的打卡计算时代,简单的命令语言用于处理卡片组。随着交互式分时系统的发展,命令语言变得更加复杂。1963 - 1964 年,Louis Pouzin 为 CTSS 编写了简单的命令解释器,1964 年他设计了扩展命令语言并创造了“shell”一词。1973 年,Ken Thompson 设计了原始的 Unix shell,随后 Stephen Bourne 和 John Mashey 对其进行扩展,Bourne 的设计成为 Unix 标准(sh)。后来,Bill Joy 开发了 C shell(csh),David Korn 开发了 ksh,而流行的 bash 是 ksh 的开源版本。
3.2 主要特性
-
文件名和变量扩展
:Unix shell 支持“通配符”扩展文件名,例如
ls *.pdf会将*.pdf扩展为所有匹配的文件名。文件名扩展也称为“globbing”,还可以指定“不关心”字符或子字符串。在循环中,文件名扩展非常有用,如:
for fig in *.eps
do
ps2pdf $fig
done
多个命令可以用分号分隔在一行输入,如
for fig in *.eps; do ps2pdf $fig; done
。
-
测试、查询和条件
:可以使用条件测试来决定是否执行某些操作。例如,只对缺少 PDF 版本的 EPS 文件创建 PDF 版本:
for fig in *.eps
do
target=${fig%.eps}.pdf
if [ $fig -nt $target ]
then
ps2pdf $fig
fi
done
- 管道和重定向 :Unix 的重要创新之一是管道,bash 使用竖线(|)表示。例如,统计目录中图形文件的数量:
for fig in *; do echo ${fig%.*}; done | sort -u | wc -l
bash 还支持输出重定向(>)和输入重定向(<),以及 stderr 和 stdout 的重定向,如
ps2pdf my_fig.eps 1>&2
表示将 stdout 发送到 stderr 的位置。此外,还支持内联输入(heredocs),如:
tr ’\n’ ’ ’ <<END
list
of
input
lines
END
- 引用和扩展 :shell 提供了多种引用机制,单引号抑制文件名和变量扩展,双引号不抑制扩展。例如:
foo=bar
single=’$foo’
double="$foo"
echo $single $double
输出为 “$foo bar”。此外,还有括号、花括号等不同的括号结构用于不同的目的,如括号用于子 shell 评估,花括号用于分组或模式列表生成。
-
函数
:用户可以在 bash 中定义函数,例如定义
ll
作为
ls -l
的快捷方式:
function ll () {
ls -l "$@"
}
-
#! 约定
:要使 shell 脚本作为可执行程序运行,需要两个步骤。首先,使用
chmod +x my_script标记文件为可执行;其次,文件开头必须以#!后跟 shell 名称,如#!/bin/bash。
4. 文本处理和报告生成
shell 语言以字符串为导向,变量为字符串值,支持丰富的字符串操作。但对于编辑任务,shell 语言并不适用,因此出现了专门用于文本处理的工具。
4.1 sed
sed 是 Unix 的“流编辑器”,用于提取 HTML 文件中的标题非常方便。例如,提取所有
<H1> - <H3>
标签内的标题:
# label (target for branch):
:top
/<[hH][123]>.*<\/[hH][123]>/ {
;# match whole heading
h
;# save copy of pattern space
s/\(<\/[hH][123]>\).*$/\1/
;# delete text after closing tag
s/^.*\(<[hH][123]>\)/\1/
;# delete text before opening tag
p
;# print what remains
g
;# retrieve saved pattern space
s/<\/[hH][123]>//
;# delete closing tag
b top
}
;# and branch to top of script
/<[hH][123]>/ {
;# match opening tag (only)
N
;# extend search to next line
b top
}
;# and branch to top of script
d
;# if no match at all, delete
sed 命令通常为单字符,适合“单行程序”,如删除标准输入中的空行:
sed -e’/^[[:space:]]*$/d’
4.2 awk
awk 是介于流编辑器和成熟脚本语言之间的工具。它保留了 sed 的逐行过滤计算模型,但允许用户在需要时跳出该模型,并使用类似 C 的语法。awk 程序由一系列模式和关联的操作组成,例如提取 HTML 标题的脚本:
/<[hH][123]>/ {
# execute this block if line contains an opening tag
do {
open_tag = match($0, /<[hH][123]>/)
$0 = substr($0, open_tag)
# delete text before opening tag
# $0 is the current input line
while (!/<\/[hH][123]>/) {
# print interior lines
print
#
in their entirety
if (getline != 1) exit
}
close_tag = match($0, /<\/[hH][123]>/) + 4
print substr($0, 0, close_tag)
# print through closing tag
$0 = substr($0, close_tag + 1)
# delete through closing tag
} while (/<[hH][123]>/)
# repeat if more opening tags
}
awk 的重要创新包括字段和关联数组。例如,打印标准输入每行的第二个单词:
awk ’print $2’
4.3 Perl
Perl 最初由 Larry Wall 于 1987 年开发,旨在结合 sed、awk 和 sh 的最佳特性。它从最初的 Unix 文本处理工具发展成为广泛使用的脚本语言,具有丰富的内置库函数和快捷方式。例如,提取 HTML 标题的 Perl 脚本:
while (<>) {
# iterate over lines of input
next if !/<[hH][123]>/;
# jump to next iteration
while (!/<\/[hH][123]>/) { $_ .= <>; }
# append next line to $_
s/.*?(<[hH][123]>.*?<\/[hH][123]>)//s;
# perform minimal matching; capture parenthesized expression in $1
print $1, "\n";
redo unless eof;
# continue without reading next line of input
}
Perl 的正则表达式功能强大,例如
. *?
可以匹配最短的字符串,并且可以在正则表达式外使用捕获的字符串。
5. 数学和统计
在数学和统计领域,也有专门的脚本语言。APL 最初是用于教学应用数学的纸笔符号,后来发展成为编程语言,具有简洁优雅的数学算法表达能力。现代的数学计算商业软件如 Maple、Mathematica 和 Matlab 提供了强大的脚本语言,用于数值方法、符号数学、数据可视化和数学建模。在统计计算方面,S 和 R 语言广泛应用,R 是 S 的开源替代方案,支持多维数组、列表类型、数组切片操作等。
6. “胶水”语言和通用脚本
脚本语言继承了文本处理和命令解释器 shell 的特性,能够准备子进程的输入并解析其输出。例如,使用 Perl 编写的“强制退出”脚本:
$#ARGV == 0 || die "usage: $0 pattern\n";
open(PS, "ps -w -w -x -o’pid,command’ |");
# ’process status’ command
<PS>;
# discard header line
while (<PS>) {
@words = split;
# parse line into space-separated words
if (/$ARGV[0]/i && $words[0] ne $$) {
chomp;
# delete trailing newline
print;
do {
print "? ";
$answer = <STDIN>;
} until $answer =~ /^[yn]/i;
if ($answer =~ /^y/i) {
kill 9, $words[0];
# signal 9 in Unix is always fatal
sleep 1;
# wait for ’kill’ to take effect
die "unsuccessful; sorry\n" if kill 0, $words[0];
}
# kill 0 tests for process existence
}
}
常见的“胶水”语言如 Tcl、Python 和 Ruby 提供了广泛的内置操作来访问操作系统的功能,同时也具备丰富的内部计算特性,如支持任意精度算术、高阶类型、类和面向对象等。
6.1 Tcl
Tcl 最初用于统一 VLSI 设计自动化工具的命令语法。它的语法相对冗长,一切都以命令形式出现。例如,“强制退出”的 Tcl 脚本:
if {$argc != 1} {puts stderr "usage: $argv0 pattern"; exit 1}
set PS [open "|/bin/ps -w -w -x -opid,command" r]
gets $PS
;# discard header line
while {! [eof $PS]} {
set line [gets $PS]
;# returns blank line at eof
regexp {[0-9]+} $line proc
if {[regexp [lindex $argv 0] $line] && [expr $proc != [pid]]} {
puts -nonewline "$line? "
flush stdout
;# force prompt out to screen
set answer [gets stdin]
while {! [regexp -nocase {^[yn]} $answer]} {
puts -nonewline "? "
flush stdout
set answer [gets stdin]
}
if {[regexp -nocase {^y} $answer]} {
set stat [catch {exec kill -9 $proc}]
exec sleep 1
if {$stat || [exec ps -p $proc | wc -l] > 1} {
puts stderr "unsuccessful; sorry"; exit 1
}
}
}
}
Tcl 的变量使用
$
符号扩展,双引号内的变量会被扩展,花括号抑制扩展,方括号用于执行 Tcl 脚本并扩展其输出。
6.2 Python
Python 由 Guido van Rossum 于 20 世纪 90 年代初开发,是面向对象的语言,具有丰富的标准库。例如,“强制退出”的 Python 脚本:
import sys, os, re, time
if len(sys.argv) != 2:
sys.stderr.write('usage: ' + sys.argv[0] + ' pattern\n')
sys.exit(1)
PS = os.popen("/bin/ps -w -w -x -o’pid,command’")
line = PS.readline()
# discard header line
line = PS.readline().rstrip()
# prime pump
while line != "":
proc = int(re.search('\S+', line).group())
if re.search(sys.argv[1], line) and proc != os.getpid():
print line + '? ',
answer = sys.stdin.readline()
while not re.search('^[yn]', answer, re.I):
print '? ',
# trailing comma inhibits newline
answer = sys.stdin.readline()
if re.search('^y', answer, re.I):
os.kill(proc, 9)
time.sleep(1)
try:
# expect exception if process
os.kill(proc, 0)
# no longer exists
sys.stderr.write("unsuccessful; sorry\n"); sys.exit(1)
except: pass
# do nothing
sys.stdout.write('')
# inhibit prepended blank on next print
line = PS.readline().rstrip()
Python 的独特之处在于使用缩进进行语法分组,正则表达式库使用方法调用的语法,并且对类型转换要求更严格。
6.3 Ruby
Ruby 是较新的通用脚本语言,由 Yukihiro “Matz” Matsumoto 开发。它是纯面向对象的语言,一切都是对象。例如,“强制退出”的 Ruby 脚本:
ARGV.length() == 1 or begin
$stderr.print("usage: #{$0} pattern\n"); exit(1)
end
pat = Regexp.new(ARGV[0])
IO.popen("ps -w -w -x -o’pid,command’") {|PS|
PS.gets
# discard header line
PS.each {|line|
proc = line.split[0].to_i
if line =~ "pat" and proc != Process.pid then
print line.chomp
begin
print "? "
answer = $stdin.gets
end until answer =~ /^[yn]/i
if answer =~ /^y/i then
Process.kill(9, proc)
sleep(1)
begin
# expect exception (process gone)
Process.kill(0, proc)
$stderr.print("unsuccessful; sorry\n"); exit(1)
rescue
# handler -- do nothing
end
end
end
}
}
Ruby 支持块和迭代器,模块机制支持扩展的混合继承,正则表达式操作可以使用标准的面向对象语法或类似 Perl 的符号。
7. 扩展语言
扩展语言用于增强应用程序的功能,允许用户使用现有命令创建新命令。许多应用程序都支持扩展,如 Adobe 的图形套件可以使用 JavaScript、Visual Basic 或 AppleScript 进行脚本编写,AOLserver 可以使用 Tcl 进行脚本编写。
以 emacs 文本编辑器为例,其扩展语言是 Emacs Lisp。例如,为选定文本区域的每行添加行号的脚本:
(setq-default line-number-prefix "")
(setq-default line-number-suffix ") ")
(defun number-region (start end &optional initial)
"Add line numbers to all lines in region.
With optional prefix argument, start numbering at num.
Line number is bracketed by strings line-number-prefix
and line-number-suffix (default \"\" and \") \")."
(interactive "*r\np")
; how to parse args when invoked from keyboard
(let* ((i (or initial 1))
(num-lines (+ -1 initial (count-lines start end)))
(fmt (format "%%%dd" (length (number-to-string num-lines))))
; yields "%1d", "%2d", etc. as appropriate
(finish (set-marker (make-marker) end)))
(save-excursion
(goto-char start)
(beginning-of-line)
(while (< (point) finish)
(insert line-number-prefix (format fmt i) line-number-suffix)
(setq i (1+ i))
(forward-line 1))
(set-marker finish nil))))
这个脚本可以通过多种方式提供给 emacs,如包含在个人启动文件中、使用
load-file
命令读取文件或使用
eval-last-sexp
命令执行。
8. 总结
脚本语言在多个领域都有广泛的应用,不同的脚本语言具有各自的特点和优势。shell 语言适用于命令操作和文件处理,文本处理工具如 sed、awk 和 Perl 用于文本处理和报告生成,数学和统计领域有专门的脚本语言,“胶水”语言如 Tcl、Python 和 Ruby 用于通用脚本编写,扩展语言则用于增强应用程序的功能。了解这些脚本语言的特性和应用场景,可以帮助开发者更高效地完成各种任务。
下面是 shell 语言操作的流程图:
graph TD;
A[开始] --> B[文件名和变量扩展];
B --> C[测试、查询和条件];
C --> D[管道和重定向];
D --> E[引用和扩展];
E --> F[函数定义];
F --> G[#! 约定执行脚本];
G --> H[结束];
不同脚本语言的特性对比表格:
| 语言 | 主要特点 | 适用场景 |
| ---- | ---- | ---- |
| sed | 单字符命令,适合单行程序,用于简单文本处理 | 快速文本替换、删除 |
| awk | 逐行过滤,支持字段和关联数组 | 文本分析、数据处理 |
| Perl | 功能丰富,正则表达式强大 | 文本处理、系统管理 |
| Tcl | 语法统一,用于命令扩展 | 工具集成、GUI 编程 |
| Python | 面向对象,使用缩进分组,标准库丰富 | 通用编程、数据科学 |
| Ruby | 纯面向对象,支持块和迭代器 | 快速开发、Web 应用 |
| Emacs Lisp | 用于 emacs 扩展 | 文本编辑自动化 |
脚本语言的多领域应用与特性解析
8. 脚本语言的应用场景总结
脚本语言在不同领域展现出了独特的优势,以下是对各脚本语言适用场景的总结:
-
系统管理
:shell 语言凭借其强大的文件操作和命令执行能力,成为系统管理任务的首选。例如,自动化文件备份、系统监控脚本等。
-
文本处理
:sed、awk 和 Perl 在文本处理方面表现出色。sed 适合简单的文本替换和删除,awk 可用于文本分析和数据提取,Perl 则以其丰富的正则表达式功能处理复杂的文本任务。
-
数学与统计计算
:APL、Maple、Mathematica、Matlab 以及 S 和 R 语言,为数学和统计领域提供了专业的计算和建模工具。
-
通用编程
:Tcl、Python 和 Ruby 作为通用脚本语言,可用于构建各种类型的应用程序,包括 Web 开发、数据处理和自动化脚本。
-
应用程序扩展
:扩展语言如 Emacs Lisp 允许用户对应用程序进行定制和扩展,提高工作效率。
9. 脚本语言的发展趋势
随着技术的不断进步,脚本语言也在不断发展和演变。以下是一些可能的发展趋势:
-
性能提升
:随着硬件性能的提高和优化技术的发展,脚本语言的执行速度将不断提升,使其能够处理更复杂的任务。
-
跨平台兼容性
:脚本语言将更加注重跨平台兼容性,能够在不同的操作系统和设备上运行。
-
与其他技术的融合
:脚本语言将与人工智能、大数据、云计算等技术融合,为开发者提供更多的工具和选择。
-
社区支持和生态系统
:强大的社区支持和丰富的生态系统将成为脚本语言发展的重要因素,促进语言的创新和应用。
10. 如何选择合适的脚本语言
在选择脚本语言时,需要考虑以下几个因素:
-
任务需求
:根据具体的任务需求选择合适的脚本语言。例如,文本处理任务可以选择 sed、awk 或 Perl,数学计算任务可以选择 Maple 或 Matlab。
-
性能要求
:如果对性能有较高的要求,可以选择编译型脚本语言或对脚本进行优化。
-
学习成本
:不同的脚本语言有不同的学习曲线,选择适合自己的语言可以提高学习效率。
-
社区支持
:选择有强大社区支持的脚本语言,可以获得更多的资源和帮助。
以下是一个选择脚本语言的决策流程图:
graph TD;
A[开始] --> B{任务需求};
B --> |文本处理| C{简单任务};
C --> |是| D[sed];
C --> |否| E{数据提取和分析};
E --> |是| F[awk];
E --> |否| G[Perl];
B --> |数学计算| H{专业需求};
H --> |是| I[Maple/Mathematica/Matlab];
H --> |否| J[Python/R];
B --> |通用编程| K{面向对象需求};
K --> |是| L{快速开发};
L --> |是| M[Ruby];
L --> |否| N[Python];
K --> |否| O[Tcl];
B --> |应用扩展| P{应用类型};
P --> |emacs| Q[Emacs Lisp];
P --> |其他| R{已有支持语言};
R --> |有| S[选择已有语言];
R --> |无| T[根据需求选择];
D --> U[结束];
F --> U;
G --> U;
I --> U;
J --> U;
M --> U;
N --> U;
O --> U;
Q --> U;
S --> U;
T --> U;
11. 脚本语言的学习建议
学习脚本语言需要耐心和实践,以下是一些学习建议:
-
选择合适的学习资源
:可以选择在线教程、书籍、视频课程等学习资源。
-
实践项目
:通过实践项目来巩固所学知识,提高编程能力。
-
参与社区
:加入脚本语言的社区,与其他开发者交流和分享经验。
-
持续学习
:脚本语言不断发展,持续学习新的特性和技术是保持竞争力的关键。
12. 总结与展望
脚本语言以其灵活性、高效性和易用性,在各个领域得到了广泛的应用。不同的脚本语言具有不同的特点和优势,开发者可以根据具体的任务需求选择合适的语言。随着技术的不断发展,脚本语言将继续演变和创新,为开发者提供更多的工具和选择。
在未来,脚本语言将在人工智能、大数据、物联网等领域发挥更加重要的作用。同时,脚本语言的性能和安全性也将得到进一步提升,为开发者提供更加稳定和可靠的开发环境。
希望通过本文的介绍,读者能够对脚本语言有更深入的了解,并在实际应用中选择合适的脚本语言。
以下是不同脚本语言学习资源的表格:
| 语言 | 学习资源 |
| ---- | ---- |
| sed | 《sed 与 awk 脚本编程》、在线 sed 教程 |
| awk | 《Effective awk Programming》、awk 官方文档 |
| Perl | 《Programming Perl》、Perl 官方网站 |
| Tcl | 《Tcl and the Tk Toolkit》、Tcl 官方文档 |
| Python | 《Python 编程从入门到实践》、Python 官方教程 |
| Ruby | 《Ruby 编程语言》、Ruby 官方网站 |
| Emacs Lisp | 《GNU Emacs Lisp Reference Manual》、Emacs 官方文档 |
超级会员免费看
4148

被折叠的 条评论
为什么被折叠?



