数据处理


Linux 启明道场.

你已经学会了通过管道传递数据、指定输入等操作。 现在,把这些知识结合起来吧! 本模块将介绍一些数据处理命令,帮助你在 shell 中完成更丰富的任务。


  • awk:进行复杂的文本处理
  • cut:提取每行中的特定部分
  • less:交互式浏览文件
  • more:分段查看文件
  • paste:合并文件
  • sed:进行复杂的文本变换
  • sort:对数据排序
  • tail:与 head 相对应,查看末尾的内容
  • uniq:过滤数据流中的重复数据

通过管道传递数据的一个目的,是对数据进行修改。 许多 Linux 命令都能以巧妙的方式修改数据。 其中之一是 tr,它的名字来自英文 translate(转换)的开头 tr:它会转换从标准输入接收到的字符,并将结果输出到标准输出。

在最基本的用法中,tr 会把第一个参数指定的字符转换为第二个参数指定的字符:

hacker@dojo:~$ echo OWN | tr O P
PWN
hacker@dojo:~$

它也能处理多个字符:第一个参数中各个位置的字符,会被替换成第二个参数中对应位置的字符。

hacker@dojo:~$ echo PWM.COLLAGE | tr MA NE
PWN.COLLEGE
hacker@dojo:~$

现在轮到你了! 在这一关中,/challenge/run 会输出 flag,但会将所有字符的大小写互换(例如,A 变成 a,反之亦然)。 你能用 tr 把它还原,拿到 flag 吗?

tr 也能把字符转换为空,也就是删除这些字符。 只需使用 -d 选项,并通过参数指定要删除的字符:

hacker@dojo:~$ echo PAWN | tr -d A
PWN
hacker@dojo:~$

很简单吧! 现在请你试一试。 在 /challenge/run 的输出中,我们会在 flag 的字符之间夹杂一些干扰字符(具体是 ^ 和 %)。 用 tr -d 把它们删除吧!

换行符是一类经常需要删除的字符。 当你想把一段数据流合并成一行,以便进一步处理时,就会用到它。 通过转义,你可以像指定其他字符一样指定换行符:

hacker@dojo:~$ echo "hello_world!" | tr _ "\n"
hello
world!
hacker@dojo:~$

这里的反斜杠(\)表示:它后面的字符用来代表一个通常很难直接输入到 shell 中的字符。 换行符当然就很难直接输入,因为按下 Enter 时,通常会直接执行命令。 \n 代表换行符,而且必须放在引号中,才能防止 shell 解释器自行解释它,让它原样传递给 tr。

现在,把它与删除操作结合起来。 在这一关中,我们会在 flag 中插入许多换行符。 使用 tr 的 -d 选项,并用转义形式指定换行符,把它们删除吧!


小知识! 如果你想替换的就是反斜杠(\)字符呢? 由于 \ 本身是转义字符,你需要对它也进行转义! \\ 会被 tr 识别为一个反斜杠。 这与本关无关,不过也是个有趣的小知识!

在学习 Linux 的过程中,你会遇到一些输出特别多的程序,而你只需要它们输出的开头部分。 这时就该用 head 了! head 命令用于显示输入的前几行:

hacker@dojo:~$ cat /something/very/long | head
this
is
just
the
first
ten
lines
of
the
file
hacker@dojo:~$

默认情况下,它显示前 10 行,但你可以用 -n 选项指定行数:

hacker@dojo:~$ cat /something/very/long | head -n 2
this
is
hacker@dojo:~$

本关中的 /challenge/pwn 会输出大量数据。你需要通过管道把数据交给 head,只提取前 7 行,再通过管道将这 7 行交给 /challenge/college。操作正确后,它就会给你 flag! 你的解答将是一条较长的组合命令,用两个管道连接三个命令。 祝你好运!

有时,你需要提取数据中的特定列,比如第一列、第三列或第 42 列。 这时可以使用 cut 命令。

例如,假设你有下面这个数据文件:

hacker@dojo:~$ cat scores.txt
hacker 78 99 67
root 92 43 89
hacker@dojo:~$

你可以用 cut 提取特定的列:

hacker@dojo:~$ cut -d " " -f 1 scores.txt
hacker
root
hacker@dojo:~$ cut -d " " -f 2 scores.txt
78
92
hacker@dojo:~$ cut -d " " -f 3 scores.txt
99
43
hacker@dojo:~$

-d 参数指定列的分隔符,也就是各列之间如何分隔。 本例中,分隔符是空格。 当然,这里的空格必须用引号括起来,shell 才知道这个空格是一个参数,而不是用于分隔其他参数的空格! -f 参数指定字段的编号,也就是要提取哪一列。

在这一关中,/challenge/run 程序会输出许多行,每行的列中包含随机数字和单个字符(flag 中的字符)。 用 cut 提取 flag 的字符,再通过管道传给 tr -d "\n"(就像前一关那样!),把它们拼接成一行。 你的解答应类似于 /challenge/run | cut ??? | tr ???,其中的 ??? 需要你补全。

文件中的行(或命令输出的行)不一定总是按照你需要的顺序排列! sort 命令可以帮助你整理数据。 它从输入(或文件)中读取各行,并按排序后的顺序输出:

hacker@dojo:~$ cat names.txt
  hack
  the
  planet
  with
  pwn
  college
hacker@dojo:~$ sort names.txt
  college
  hack
  planet
  pwn
  the
  with
hacker@dojo:~$

默认情况下,sort 按字母顺序对各行排序。 可以用参数改变排序方式:

  • -r:逆序排列(从 Z 到 A)
  • -n:按数值排序(适用于数字)
  • -u:只保留不重复的行(去重)
  • -R:随机排列!

在这一关中,/challenge/flags.txt 文件包含 100 个假 flag,真正的 flag 混在其中。 按字母顺序排序后,真正的 flag 会出现在最后(生成假 flag 时,我们已经确保了这一点)。 去把它找出来吧!


30天排行榜:

此排行榜反映本模块在道场上线后各挑战的解出情况。

排名 黑客 徽章 得分
暂无解题排行数据 —— 注册账号并完成挑战即可登上榜单!