2.4 Linux命令行

本节会简单介绍一下在使用GMT的过程中需要掌握的一些与GMT无关的基础知识。这些基础知识多数是以平台无关的,既适用于Linux也适用于Windows,个别仅适用于Linux。由于我几乎不在Windows下用GMT,所以这里所说的均以Linux为准,对Windows仅供参考。

2.4.1 终端

终端在Linux下称为terminal。打开终端后,在终端键入如下命令:

$ gmt pscoast -R70/140/2/60 -Ggray -JM6i -Wthin -B5 -V -P > map.ps
pscoast: GSHHG version 2.3.4
Derived from World Vector Shoreline, CIA WDB-II, and Atlas of the Cryosphere
Processed by Paul Wessel and Walter H. F. Smith, 1994-2014
pscoast: Working on bin #   301
pscoast: Done

上面的命令会绘制中国及其周边的海岸线数据,图片保存到map.ps中,可以用gs命令查看:

$ gs map.ps

终端在Windows下称为cmd。“开始”->“附件”->“命令提示符”即可启动cmd,也可以直接在开始按钮中的搜索框中直接搜索“cmd”。在cmd中键入上面的绘图命令即可绘制图形。直接双击生成的PS文件即可用gsview查看绘图效果。

2.4.2 脚本

一张稍复杂的图通常都需要多个GMT命令来完成。你可以在终端键入如下两个命令来绘制海岸线并在某个点处加一个五角星:

gmt pscoast -R70/140/2/60 -Ggray -JM6i -W1/thin -B5 -K -P > map.ps
echo 115 40 | gmt psxy -R70/140/2/60 -JM6i -Sa0.5c -Gred -O >> map.ps

直接在终端敲命令是不是很麻烦?一旦敲错了就得把光标移过去重新编辑,或者哪里不满意想修改,还得查找命令历史把命令找出来重新执行一遍,又或者一个不小心命令历史丢了,原来的画图命令再也找不到了。这一切都可以通过脚本来解决。

以Linux为例,新建一个名为 test.sh 的文件,将上面的两行命令复制到文件中并保存就完成了一个脚本,然后在终端中键入如下命令即可执行该脚本:

$ sh ./test.sh

对于Windows用户,可以将上面的两行命令复制到名为 test.bat 的文件内并保存,然后双击该bat文件即可执行脚本。

Linux下最基础的脚本语言是bash,Windows下则是bat,当然还有跨平台的Perl和Python。本文档的所有示例都使用bash语法。

脚本最最简单的用法就是像上面的示例那样,把一堆要执行的命令复制进去即可,但脚本的功能可不仅仅如此,要学会善于利用脚本语言的强大功能,比如:

  1. 定义变量,代替命令中重复的部分
  2. 用脚本语言完成计算与数据处理
  3. 利用脚本实现循环
  4. 利用脚本的命令行参数实现脚本的可复用性

2.4.3 后缀

经常接触的 .doc.ppt ,以及上面提到的 .sh.bat.ps 等,都是文件后缀,文件后缀的主要作用是表明该文件是什么格式或什么类型的文件。

Windows下,每一个文件后缀都与特定的应用程序相关联,比如后缀为 .doc 的文件默认都是用MS Word打开,当然也可以选择用其他应用程序打开。后缀为 .bat 的文件,在双击的时候会直接被执行,想要编辑的话就需要右键编辑。

Linux下,文件后缀就没那么重要了。一个bash脚本可以用 .sh 结尾,也可以用 .gmt 结尾,甚至没有后缀。不管后缀是什么,如果用 sh 来执行该脚本,这个脚本就会被当成bash脚本;如果用 perl 来执行该脚本,这个脚本就会被当成Perl脚本(bash脚本被当成Perl脚本来解释,会直接报错)。因而在Linux下,对文件的后缀并没有严格的要求,后缀的作用仅仅是让用户一眼就可以看出来文件是什么格式而已。

2.4.4 标准输出流和标准错误流

标准输出流(STDOUT)用于显示输出数据,标准错误流(STDERR)用于显示错误消息。一般来说,标准输出流和标准错误流都是屏幕。

GMT中,模块的正常输出都发送到标准输出流,模块的语法、警告、错误以及进程报告都发送到标准错误流,由于这两者默认情况下都是屏幕,所以标准输出流和标准错误流会混在一起,因而需要对输出进行重定向。常见的做法可以是下面的一种或多种的组合:

  1. 将标准输出流重定向到数据文件中
  2. 将标准错误流重定向到日志文件中
  3. 将标准输出流通过管道传递给下一个命令

2.4.5 重定向

这里只介绍GMT中经常使用的最简单的重定向功能。

对于标准输出流:

  • > :将标准输出流重定向到新文件中。若该文件已存在,则覆盖文件中原内容;若该文件不存在,则创建该文件
  • >> :将标准输出流追加到文件中。若文件已存在,则将标准输出流追加到已有文件后面;若文件不存在,则创建该文件

对于标准错误流,重定向符号是 2>2>> 。这里的 2 表示标准错误流,大于号的含义与标准输出流相同。

GMT中最常用的是对标准输出流的重定向。前面说过,GMT的绘图模块会生成一堆PS代码,并发送到标准输出流中。默认情况下这些代码会显示在屏幕上,因而需要对标准输出流做重定向:

gmt psxy -R70/140/2/60 -JM6i -T -K -P > map.ps
gmt pscoast -R70/140/2/60 -Ggray -JM6i -W1/thin -B5 -K -O >> map.ps
echo 115 40 | gmt psxy -R70/140/2/60 -JM6i -Sa0.5c -Gred -K -O >> map.ps
gmt psxy -R70/140/2/60 -JM6i -T -O >> map.ps

上例中的四个命令中都对标准输出流进行了重定向,第一个命令使用 > 将生成的PS代码发送到新文件中,其余命令则使用 >> 将PS代码追加到已有文件中。

2.4.6 管道

除了上面提到的重定向符号之外,还有一种常用的类似重定向的操作,即管道,用符号 | 表示。

管道的作用是,将上一个命令的标准输出作为下一个命令的标准输入。

举例如下,假设文件 input.dat 中包含了一系列地震的经度、纬度和震级共三列数据,想要在图上画很多圆表示地震的位置,圆的大小表示震级的大小。可以用类似如下命令:

gmt psxy input.dat -Rxxx ... > test.ps

此时 psxy 模块会读取 input.dat 文件的内容作为其输入。

也可以使用管道:

cat input.dat | gmt psxy ... > test.ps

cat 命令会读取 input.dat 的内容并将其发送到标准输出流,由于使用了管道,标准输出流中的内容被 gmt psxy 接收作为自己的标准输入流。

当然还可以使用 gawk

gawk '{print $1, $2, $3/10}' input.dat | gmt psxy ... > test.ps

gawk 会读取 input.dat 的内容,并对数据做简单处理并输出。

2.4.7 标准输入流

GMT的某些模块需要数据才可以画图,这些数据可以来自于文件,或来自于标准输入流。

比如要绘制地震的分布,可以把地震的经纬度信息放在文件 event.loc 中,其内容如下:

100.0 40.0
110.0 45.0

将这些数据传给GMT有如下几种方法。

  1. 直接在命令行指定文件名,命令会自动读取该文件的内容:

    gmt psxy event.loc -R70/140/20/60 -JM6i -B5 -Sc0.2c -Gred -P > map.ps
    
  2. 直接从键盘输入

    标准输入流的默认设备是键盘。下面的例子中直接从键盘输入GMT所需的数据。首先执行 gmt psxy 命令,然后键盘键入两行数据,再按下 Ctrl+C 中断输入,GMT会给出中断警告,然后按下回车键即可:

    $ gmt psxy -R70/140/20/60 -JM6i -B5 -Sc0.2c -Gred -P > map.ps
    100.0 40.0
    110.0 45.0
    Interrupt at /lib64/libc.so.6(__read+0x10)[0x7f8383e8d980]
    Tuser: 0.004s Tsys: 0.004s VmRSS: 8340kB VmSize: 114268kB
    Press return to continue, ctrl-c to quit.
    $
    
  3. 标准输入流重定向 <

    < 的作用是读取 < 后的文件的内容并将其作为标准输入流,与直接在命令行指定文件名类似:

    gmt psxy -R70/140/20/60 -JM6i -B5 -Sc0.2c -Gred -P > map.ps < event.loc
    
  4. 通过管道输入

    管道可以将前一个命令的标准输出作为后一个命令的标准输入:

    cat event.loc | gmt psxy -R70/140/20/60 -JM6i -B5 -Sc0.2c -Gred -P > test.ps
    
  5. Here Documents

    示例如下,两个 EOF 之间的所有数据都会被传递给GMT:

    gmt psxy -R70/140/20/60 -JM6i -B5 -Sc0.2c -Gred -P > map.ps << EOF
    100.0 40.0
    110.0 45.0
    EOF
    

说明:

  1. 上面列出的5种方式中,常用的是第1、4、5种;
  2. Here Documents方法中, EOF 可以被替换成其他任意字符(比如 END ),只要保证开始和结束的符号一致即可
  3. Here Documents方法仅适用于bash,不适用于bat

2.4.8 倒引号

倒引号,也称为反引号,英文为backtick或backquote。倒引号的作用是将一个命令的标准输出插在另一个命令的任意位置。

例如,想要用 psxy 绘制某数据时,需要提供数据的范围 -R ,而 gmtinfo 模块可以用于计算并输出数据的范围,即需要将 gmtinfo 的输出作为 psxy 的一个选项。

比如:

$ gmt info in.dat -I1/1
-R0/10/0/10
$ gmt psxy in.dat -JX10c -R0/10/0/10 > map.ps

上面的做法需要人工干预,不适合脚本自动化,可以利用倒引号将 gmtinfo 的输出保存到变量中:

#!/bin/bash

R=`gmt info input -I1/1`
gmt psxy in.dat -JX10c $R > map.ps

上面的例子还可以进一步简化。此处变量 $R 只需要用一次,因而没有必要把 gmtinfo 的输出信息保存到变量中,可以直接在 psxy 命令中使用倒引号:

$ gmt psxy in.dat -JX10c `gmt info in.dat -I1/1` > map.ps

此处,bash首先会执行倒引号内的命令,然后用 gmtinfo 的输出替换整个倒引号部分,再执行替换后的命令。这样的写法更易于自动化。

2.4.9 通配符

UNIX下提供了通配符功能,使得可以基于文件名的模式选择一组文件。

UNIX下的通配符包括:

表 2.1 通配符
通配符 含义
* 匹配任意数目的任意字符
? 匹配任意单个字符
[ABC] 匹配中括号内的任意单个字符
[A-Z] 匹配给定范围内的任意单个字符

示例:

  1. data_*.d 会匹配所有以 data_ 开头,并以 .d 结尾的文件
  2. line_?.d 会匹配所有以 line_ 开头,后接任意一个字符,并以 .d 结尾的文件
  3. section_1[0-9]0.part 会匹配 section_1x0.partx 为0到9的文件
  4. section_[12].part 会匹配 section_1.partsection_2.par 两个文件