[Linux]Text-Fu

Text-Fu

1 stdout

1
$ echo Hello World > peanuts.txt

运行该命令后,发生了什么?检查执行该命令的目录,能看到一个名为peanuts.txt的文件。查看该文件内部,看到文本“Hello World”。这一命令中涉及多个概念。

首先解析第一部分:

1
$ echo Hello World

这条命令会将“Hello World”打印到屏幕上。进程通过I/O流接收输入并返回输出。默认情况下,echo命令从键盘获取输入(标准输入或stdin),并将输出(标准输出或stdout)显示在屏幕上。因此,在shell中输入echo Hello World时,屏幕上就会显示“Hello World”。然而,I/O重定向允许我们改变这种默认行为,提供更大的文件操作灵活性。

接着解析命令的下一部分:

使用>作为重定向操作符,它改变了标准输出的目的地。这样我们可以将echo Hello World的输出发送到文件而非屏幕。如果文件不存在,它会自动创建;若文件已存在,则会覆盖原文件(根据所使用的shell,可以添加一个标志来防止这种情况)。

这就是基本的标准输出重定向的工作方式。

假设我们不希望覆盖已有的peanuts.txt文件,有一个专门用于追加内容的重定向操作符>>

1
$ echo Hello World >> peanuts.txt

这将把“Hello World”附加到peanuts.txt文件末尾。如果文件不存在,它也会自动创建。

2 stdin

我们也能够利用多种标准输入(stdin)流,如来自键盘的输入、文件、其他进程的输出以及终端。下面通过一个例子来说明。

使用上面的peanuts.txt文件作为例子,记得里面包含了“Hello World”文本。

1
$ cat < peanuts.txt > banana.txt

正如我们使用>进行标准输出重定向一样,也可以用<进行标准输入重定向。

通常情况下,在使用cat命令时,我们会将一个文件传递给它,该文件即成为标准输入。在这个例子中,我们通过<操作符将peanuts.txt重定向为标准输入。然后,cat peanuts.txt的输出——即“Hello World”,被重定向到另一个名为banana.txt的文件中。

3 stderr

尝试列出系统中不存在的目录内容,并将输出再次重定向到peanuts.txt文件。

执行以下命令:

1
$ ls /fake/directory > peanuts.txt

会看到如下错误信息:

1
ls: cannot access /fake/directory: No such file or directory

这里涉及到另一个输入输出流——标准错误(stderr)。默认情况下,stderr同样会将其输出显示在屏幕上,它是与stdout完全独立的流。因此,需要以不同的方式重定向其输出。

不同于使用<>那样直观,stderr的重定向需要用到文件描述符。文件描述符是一个用于访问文件或流的非负整数。stdin、stdout和stderr的文件描述符分别是0、1和2。

若要将stderr重定向到文件,可以这样做:

1
$ ls /fake/directory 2> peanuts.txt

这样,只有stderr的信息会被写入peanuts.txt文件中。

如果希望同时捕获stderr和stdout的信息到peanuts.txt文件,可以通过以下方式实现:

1
$ ls /fake/directory > peanuts.txt 2>&1

此命令首先将ls /fake/directory的结果输出到peanuts.txt文件,然后通过2>&1将stderr重定向到当前stdout指向的位置。在这个例子中,由于stdout指向一个文件,stderr也会被重定向至同一文件。因此,打开peanuts.txt文件时,你应该能看到stderr和stdout的信息。对于上述命令,实际只会输出stderr的内容。

还有一种更简洁的方式将stdout和stderr同时重定向到一个文件:

1
$ ls /fake/directory &> peanuts.txt

如果你不希望处理任何错误信息,并想彻底忽略stderr的消息,可以将输出重定向到特殊文件/dev/null,它会丢弃所有输入:

1
$ ls /fake/directory 2> /dev/null

4 pipe and tee

有一个非常实用的操作是将一个命令的输出作为另一个命令的输入。首先尝试以下命令:

1
$ ls -la /etc

这将展示/etc目录下的详细文件列表,但直接查看可能信息量过大难以阅读。此时,我们可以不将输出重定向至文件,而是利用less等命令来优化查看方式:

1
$ ls -la /etc | less

这里使用的管道符|能够将前一个命令的标准输出(stdout)连接到下一个命令的标准输入(stdin)。上述例子中,我们通过管道将ls -la /etc的输出传递给了less命令,使得浏览长列表变得更为便捷。管道符是极为有用的工具,在数据处理过程中经常被使用。

若需要将命令的输出同时保存到文件并显示在终端上,可以采用tee命令实现:

1
$ ls | tee peanuts.txt

执行此命令后,不仅能在屏幕上看到ls命令的实时输出,也能在同一时间将这些信息写入peanuts.txt文件中。这意味着,无论是在即时查看还是后续查阅记录时,都能获取一致的信息内容。这种方式非常适合既需要即时查看输出又希望保存副本用于后续参考的情景。

5 env(environment)

执行以下命令以查看当前用户的主目录路径:

1
$ echo $HOME

这将显示类似/home/pete的路径,具体取决于用户名。再尝试另一条命令:

1
$ echo $USER

这条命令会输出用户名。这些信息源自于环境变量。

要查看所有当前设置的环境变量,可以使用env命令:

1
$ env

该命令会列出大量关于环境变量的信息,这些变量中包含了对shell及其他进程有用的数据。下

特别重要的是PATH变量,它指定了系统在执行命令时搜索可执行文件的路径列表。可以通过如下方式访问这个变量:

1
$ echo $PATH

此命令返回一系列由冒号分隔的路径。假设从互联网下载并安装了一个软件包到非标准目录,并希望运行该命令,但输入$ coolcommand后提示“command not found”。即使能直接看到该二进制文件存在于指定文件夹中,但如果该文件夹未包含在$PATH变量中,系统就无法找到并执行该命令。

如果需要经常从特定目录运行多个可执行文件,只需修改PATH环境变量,将其添加至搜索路径中即可。例如,若要添加/custom/pathPATH变量,可以在终端中输入:

1
$ export PATH=$PATH:/custom/path

这样,系统在执行命令时也会在新添加的目录中进行搜索。

当使用export在终端会话中添加或修改环境变量时,这些更改仅对当前的终端会话有效。一旦关闭了该终端会话或者重新启动系统,这些更改就会丢失。

如果希望环境变量是永久性的,需要将其添加到shell配置文件中。

在Bash中,可以打开~/.bashrc文件,并在文件末尾添加如下行来永久改变PATH变量:

1
export PATH=$PATH:/your/new/path

完成编辑后保存文件,并运行source ~/.bashrc使更改立即生效。

6 cut

先创建一个用于操作的文件。

1
$ echo 'The quick brown; fox jumps over the lazy	dog' > sample.txt

cut命令,可以从文件中提取文本片段。

  • 使用字符列表提取内容:
1
$ cut -c 5 sample.txt

上述命令会输出文件每行中的第5个字符,在此例中为”q”。请注意,空格也被计为一个字符。

-c参数允许指定要提取的字符列的位置。可以指定单个字符位置(例如,-c 5将提取每行的第5个字符),也可以指定一个范围(例如,-c 1-10将提取每行的前10个字符)。此外,还可以指定多个不连续的字符位置或范围,中间用逗号分隔(例如,-c 1-3,7将提取每行的第1到第3个字符以及第7个字符)。

  • 按照字段提取内容:
1
$ cut -f 2 sample.txt

这里,-f(field字段)标志根据字段切割文本,默认情况下使用TAB作为分隔符。因此,由TAB分隔开的每一部分被视为一个字段。执行该命令后,将看到输出为”dog”。

还可以结合使用字段标志和定界符标志来通过自定义分隔符提取内容:

1
$ cut -f 1 -d ";" sample.txt

这条命令将分隔符从默认的TAB改为”;”,所以结果应为”The quick brown”。

7 paste

paste命令与cat命令类似,它可以将文件中的多行合并。首先,创建一个包含以下内容的新文件:

sample2.txt

1
2
3
4
The
quick
brown
fox

接下来,将这些行合并成一行:

1
$ paste -s sample2.txt

默认情况下,paste使用的分隔符是TAB,因此上述命令执行后,所有单词会被TAB键分隔并显示在同一行。

若要使分隔符更易读,可以将其修改为空格:

1
$ paste -d ' ' -s sample2.txt

8 head

假设有一个非常长的文件,实际上有很多可供选择的文件,我们可以使用cat /var/log/syslog命令查看。你会看到文本一页接一页地显示。如果只想查看这个文本文件的前几行,可以使用head命令,默认情况下,它会显示文件的前10行。

要查看/var/log/syslog文件的前10行,可以执行:

1
$ head /var/log/syslog

若需要指定行数,比如希望查看前15行,可以使用-n选项进行设置:

1
$ head -n 15 /var/log/syslog

这里的-n标志用于指定显示的行数。

9 tail

类似于head命令,tail命令默认情况下显示文件的最后10行:

1
$ tail /var/log/syslog

head命令一样,可以通过-n选项自定义希望查看的行数。

此外,tail命令提供了一个非常有用的选项-f(跟随),它允许实时跟踪文件的增长。当你在系统上执行操作时,尝试使用以下命令观察结果:

1
$ tail -f /var/log/syslog

当与系统交互时,syslog文件会持续更新,而通过tail -f命令,你可以实时监控所有新添加到该文件的内容。这一功能对于调试和监控特别有用。

10 expand and unexpand

通常情况下,制表符会在文本中显示出明显的间距差异,但某些文本文件可能无法清晰地体现这种差异。若文件中的制表符未能达到预期的间距效果,可以使用expand命令将制表符转换为空格。

执行如下命令可将sample.txt文件中的每个制表符转换为一组空格并打印输出:

1
$ expand sample.txt

如果需要将此输出保存到一个新文件中,可以使用输出重定向功能,例如:

1
$ expand sample.txt > result.txt

相反地,若需将空格转换回制表符,可以使用unexpand命令。特别是使用-a选项时,可以将result.txt文件中的所有合适空格组转换为制表符:

1
$ unexpand -a result.txt

这些命令提供了调整文本文件格式的简便方法,使得文本显示更加符合用户的需求。

11 join and split

join命令允许用户通过一个共同字段来合并多个文件。

假设有两个需要合并的文件,它们内容如下:

file1.txt

1
2
3
1 John
2 Jane
3 Mary

file2.txt

1
2
3
1 Doe
2 Doe
3 Sue

默认情况下,join命令会根据第一个字段进行合并,且要求这些字段完全相同。执行以下命令将会基于共同的第一个字段将两个文件合并:

1
$ join file1.txt file2.txt

输出结果:

1
2
3
1 John Doe
2 Jane Doe
3 Mary Sue

如果文件格式不同,例如:

file1.txt

1
2
3
John 1
Jane 2
Mary 3

file2.txt

1
2
3
1 Doe
2 Doe
3 Sue

在这种情况下,我们需要明确指定要合并的字段。对于上述情况,我们将file1.txt的第二个字段与file2.txt的第一个字段进行合并。对应的命令如下所示:

1
$ join -1 2 -2 1 file1.txt file2.txt

这里,-1 2指定了file1.txt中用于合并的字段是第2个字段,而-2 1则指定了file2.txt中用于合并的是第1个字段。结果将与前例相同。

此外,还可以利用split命令将一个大文件分割成若干个小文件。例如,执行以下命令可以将somefile按每1000行分割为新文件,默认命名格式为x**:

1
$ split somefile

可以使用 -l 参数来修改每个文件的行数。

12 sort

sort命令用于对文件中的行进行排序。

以下是如何使用该命令的一些示例:

假设有一个名为file1.txt的文件,内容如下:

1
2
3
4
5
dog
cow
cat
elephant
bird

执行以下命令将根据字母顺序对这些行进行排序:

1
$ sort file1.txt

排序后的输出结果为:

1
2
3
4
5
bird
cat
cow
dog
elephant

若要进行逆序排序,可以使用-r选项:

1
$ sort -r file1.txt

逆序排序的结果为:

1
2
3
4
5
elephant
dog
cow
cat
bird

此外,对于包含数值的数据,可以使用-n选项按照数值大小进行排序。

13 tr(translate)

tr命令(translate的缩写)用于将一组字符转换为另一组字符。

以下是一个将所有小写字母转换为大写的示例。

1
$ echo hello | tr a-z A-Z

输出结果将是:

1
HELLO

14 uniq(unique)

uniq(unique的缩写)命令可以从文本文件中删除重复的行,或者对重复行进行计数等操作。

假设有一个名为reading.txt的文件,内容如下:

1
2
3
4
5
6
7
book
book
paper
paper
article
article
magazine

删除重复行

要删除上述文件中的重复项,可以使用uniq命令:

1
$ uniq reading.txt

输出结果将是:

1
2
3
4
book
paper
article
magazine

获取重复行的计数

若要统计每行出现的次数,可以使用-c选项:

1
$ uniq -c reading.txt

输出结果将是:

1
2
3
4
2 book
2 paper
2 article
1 magazine

仅获取唯一的行

如果只对唯一出现的行感兴趣,可以使用-u选项:

1
$ uniq -u reading.txt

输出结果将是:

1
magazine

仅获取重复的行

同样地,若只想查看那些出现了不止一次的行,则可以使用-d选项:

1
$ uniq -d reading.txt

输出结果将是:

1
2
3
book
paper
article

注意事项

uniq命令不会检测非相邻的重复行。例如,对于以下不相邻的重复行:

1
2
3
4
5
6
7
book
paper
book
paper
article
magazine
article

直接使用uniq reading.txt将无法移除非相邻的重复项。为解决这一问题,可结合sortuniq命令一起使用:

1
$ sort reading.txt | uniq

这样就能得到无重复的排序后的输出:

1
2
3
4
article
book
magazine
paper

通过这种方式,可以有效地去除文本文件中的重复行,并按需进行进一步处理。

15 wc and nl

wc(word count)命令用于显示文件中字节、单词和行的总数。例如,使用以下命令:

1
$ wc /etc/passwd

输出可能如下所示:

1
96 265 5925 /etc/passwd

上述结果分别表示:行数、单词数以及字节数。

选择特定计数

若仅需获取特定项的计数,可以使用下列选项:

  • -l:仅显示行数。
  • -w:仅显示单词数。
  • -c:仅显示字节数。

nl 命令

另一个用于统计文件行数的工具是nl(number lines)命令。它不仅能够计算行数,还能为每一行添加行号。

例如,有一个名为file1.txt的文件,内容如下:

1
2
3
i
like
turtles

使用nl命令处理该文件:

1
$ nl file1.txt

输出将为:

1
2
3
1. i
2. like
3. turtles

16 grep

grep命令允许在文件中搜索符合特定模式的字符。如果想知道某个目录中是否存在某个文件,或者想查看一个字符串是否出现在某个文件中,无需逐行检查文本,只需使用grep命令即可。

以sample.txt文件为例:

1
$ grep fox sample.txt

上面的命令将会查找并显示sample.txt文件中包含”fox”的所有行。

若要进行不区分大小写的模式匹配,可以使用-i选项:

1
$ grep -i somepattern somefile

为了使grep更加灵活,可以将其与其他命令结合使用,通过管道符“|”实现:

1
$ env | grep -i User

甚至可以在模式中使用正则表达式:

1
$ ls /somedir | grep '.txt$'

此命令将返回指定目录”/somedir”下所有以”.txt”结尾的文件。

17 regex

正则表达式是一种强大的模式匹配工具,它使用特殊符号进行选择,类似于我们已经遇到的通配符*等。

下面是一些几乎在所有编程语言中都通用的常见正则表达式示例。我们将使用以下短语作为测试字符串:

1
2
sally sells seashells 
by the seashore
  1. 使用^表示行的开始

例如,^by将匹配“by the seashore”这一行。

  1. 使用$表示行的结束

例如,seashore$同样匹配“by the seashore”这一行。

  1. 使用.匹配任意单个字符

例如,b.能够匹配“by”。

  1. 使用[]进行括号标记

这可能稍微复杂一些。方括号允许我们指定出现在其中的字符。例如,

  • d[iou]g可以匹配“dig”、“dog”、“dug”。
  • 当^位于方括号内时,表示匹配不在方括号内的任何字符。例如,d[^i]g能匹配“dog”和“dug”,但不匹配“dig”。
  • 方括号还支持范围来扩展可匹配字符的数量。如d[a-c]g将匹配“dag”、“dbg”和“dcg”。

需要注意的是,方括号是区分大小写的:

  • d[A-C]g将匹配“dAg”、“dBg”和“dCg”,但不匹配“dag”、“dbg”和“dcg”。

以上是一些基础的正则表达式的应用。

18 vim

在 Vim 编辑器中执行搜索时,只需键入斜杠(/)然后输入你的搜索内容即可。按下回车后,可以按“n”键向前或“N”键向后浏览搜索结果。

例如,对于以下文本:

1
My pretty file is very pretty.

使用 /pretty 将会找到文本中的 “pretty” 一词。

另外,使用 ? 命令可以反向搜索文档。

编辑

一些常用的进入插入模式的方法:

  • i: 在光标前插入文本。
  • O: 在上一行插入文本。
  • o: 在下一行插入文本。
  • a: 在光标后追加文本。
  • A: 在行尾追加文本。

几个常用的编辑命令:

  • x:用于删除光标所在位置的字符,也可用于删除已选中的文本。
  • dd:删除当前行。
  • y:复制选中的文本。使用时,先通过其他命令(如 v 视觉模式)选择文本,然后按 y 复制。
  • yy:直接复制当前行。
  • p:在光标位置之前粘贴已复制的文本。

保存

使用 ZZ 代替 :wq


[Linux]Text-Fu
https://erlsrnby04.github.io/2025/03/18/Linux-Text-Fu/
作者
ErlsrnBy04
发布于
2025年3月18日
许可协议