13种基于外壳的文字处理工具

这是Balthazar Ruberol和Etienne Broad编着的未来书籍《面向新手软件开发人员的基本工具和实践》的一部分这本书应该有助于教育年轻的开发人员。它将涵盖以下主题:掌握控制台,在命令外壳中进行设置和有效地工作,使用gitSQL基础知识管理代码版本,诸如和正则表达式之类的工具Makejq网络基础知识以及软件开发和协作的最佳实践。作者目前正在这个项目上努力工作,并邀请每个人参加邮件列表

内容



外壳文字处理


使命令外壳成为无价工具的原因之一是大量的文字处理命令,并且能够轻松地将它们组合到管道中,从而创建复杂的处理模板。这些命令使许多任务变得微不足道,这些任务对于分析文本和数据,在不同格式之间转换数据,过滤字符串等非常重要。

在处理文本数据时,主要原理是将任何复杂的问题分解为许多较小的问题-并分别解决他们使用专用工具。

使每个程序做好一件事情-Unix哲学基础

乍一看,本章中的示例似乎有些牵强,但这是有目的的。每个工具都旨在解决一个小问题。但是,当结合使用时,它们将变得异常强大。

我们将在命令外壳中介绍一些最常用和有用的文本处理命令,并演示将它们连接在一起的实际工作流程。我建议您查看这些团队的法力,以了解可支配的全部可能性。

可以在线获取示例CSV文件您可以下载它来检查材料。


该命令cat用于编译一个或多个文件的列表,并将其内容显示在屏幕上。

$ cat Documents/readme
Thanks again for reading this book!
I hope you're following so far!

$ cat Documents/computers
Computers are not intelligent
They're just fast at making dumb things.

$ cat Documents/readme Documents/computers
Thanks again for reading this book!
I hope you are following so far!

Computers are not intelligent
They're just fast at making dumb things.


head打印文件中的前n行。这对于查找结构和格式未知的文件而不用一堆文本填充整个控制台非常有用。

$ head -n 2 metadata.csv
metric_name,metric_type,interval,unit_name,per_unit_name,description,orientation,integration,short_name
mysql.galera.wsrep_cluster_size,gauge,,node,,The current number of nodes in the Galera cluster.,0,mysql,galera cluster size

如果-n未指定,则head打印指定文件或输入流的前十行。

尾巴


tail-类似物head,仅显示文件的最后n行。

$ tail -n 1 metadata.csv
mysql.performance.queries,gauge,,query,second,The rate of queries.,0,mysql,queries

如果要打印位于第n行(包括它)之后的所有行,则可以使用参数-n +n

$ tail -n +42 metadata.csv
mysql.replication.slaves_connected,gauge,,,,Number of slaves connected to a replication master.,0,mysql,slaves connected
mysql.performance.queries,gauge,,query,second,The rate of queries.,0,mysql,queries

我们的文件中有43行,因此它tail -n +42仅从中输出第42行和第43行。

如果-n未指定该参数,它将tail在指定的文件或输入流中输出最后十行。

tail -ftail --follow显示文件中的最后几行以及写入到文件中的每一行。这对于实时查看活动非常有用,例如,Web服务器日志中记录的内容等。

厕所


wc(字数统计)显示指定文件或流中的字符数(-c),单词数(-w)或行数(-l)。

$ wc -l metadata.csv
43  metadata.csv
$ wc -w metadata.csv
405 metadata.csv
$ wc -c metadata.csv
5094 metadata.csv

默认情况下,将显示所有上述内容。

$ wc metadata.csv
43     405    5094 metadata.csv

如果文本数据通过管道传输或重定向到stdin,则仅显示计数器。

$ cat metadata.csv | wc
43     405    5094
$ cat metadata.csv | wc -l
43
$ wc -w < metadata.csv
405

grep


grep-这是一把瑞士刀,可以根据给定的模式过滤弦。

例如,我们可以找到文件中所有出现的互斥单词

$ grep mutex metadata.csv
mysql.innodb.mutex_os_waits,gauge,,event,second,The rate of mutex OS waits.,0,mysql,mutex os waits
mysql.innodb.mutex_spin_rounds,gauge,,event,second,The rate of mutex spin rounds.,0,mysql,mutex spin rounds
mysql.innodb.mutex_spin_waits,gauge,,event,second,The rate of mutex spin waits.,0,mysql,mutex spin waits

grep可以处理指定为参数的文件或传递给它的文本流stdin因此,我们可以连接几个命令grep以进一步过滤文本。在下面的示例中,我们过滤文件metadata.csv中的行以查找包含互斥体OS的行

$ grep mutex metadata.csv | grep OS
mysql.innodb.mutex_os_waits,gauge,,event,second,The rate of mutex OS waits.,0,mysql,mutex os waits

让我们考虑一些选项grep及其行为。

grep -v执行逆向匹配:过滤与参数模式匹配的字符串

$ grep -v gauge metadata.csv
metric_name,metric_type,interval,unit_name,per_unit_name,description,orientation,integration,short_name

grep -i执行不区分大小写的匹配。以下示例grep -i os查找OSos

$ grep -i os metadata.csv
mysql.innodb.mutex_os_waits,gauge,,event,second,The rate of mutex OS waits.,0,mysql,mutex os waits
mysql.innodb.os_log_fsyncs,gauge,,write,second,The rate of fsync writes to the log file.,0,mysql,log fsyncs

grep -l 列出包含匹配项的文件。

$ grep -l mysql metadata.csv
metadata.csv

该团队grep -c计算发现样本的次数。

$ grep -c select metadata.csv
3

grep -r 在当前工作目录及其所有子目录中递归搜索文件。

$ grep -r are ~/Documents
/home/br/Documents/computers:Computers are not intelligent
/home/br/Documents/readme:I hope you are following so far!

grep -w 仅显示匹配的整个单词。

$ grep follow ~/Documents/readme
I hope you are following so far!
$ grep -w follow ~/Documents/readme
$


cut提取文件的一部分(或照常输入流)。该命令使用option定义字段分隔符(用于分隔列)-d,并使用option 定义要检索的列号-f

例如,以下命令从CSV文件的最后五行中检索第一列。

$ tail -n 5 metadata.csv | cut -d , -f 1
mysql.performance.user_time
mysql.replication.seconds_behind_master
mysql.replication.slave_running
mysql.replication.slaves_connected
mysql.performance.queries

由于我们正在处理CSV,因此各列之间用逗号分隔,并且该选项负责检索第一列-f 1

您可以使用选项选择第一列和第二列-f 1,2

$ tail -n 5 metadata.csv | cut -d , -f 1,2
mysql.performance.user_time,gauge
mysql.replication.seconds_behind_master,gauge
mysql.replication.slave_running,gauge
mysql.replication.slaves_connected,gauge
mysql.performance.queries,gauge


paste 将两个不同的文件合并到一个多列文件中。

$ cat ingredients
eggs
milk
butter
tomatoes
$ cat prices
1$
1.99$
1.50$
2$/kg
$ paste ingredients prices
eggs    1$
milk    1.99$
butter  1.50$
tomatoes    2$/kg

默认情况下,它paste使用制表符分隔符,但可以使用参数进行更改-d

$ paste ingredients prices -d:
eggs:1$
milk:1.99$
butter:1.50$
tomatoes:2$/kg

另一个常见用例paste 是使用指定的定界符,并结合使用-s来组合流或文件中的所有行-d

$ paste -s -d, ingredients
eggs,milk,butter,tomatoes

如果将参数指定为输入文件-,则将改为读取它stdin

$ cat ingredients | paste -s -d, -
eggs,milk,butter,tomatoes

分类


该命令sort实际上对数据进行排序(在指定的文件或输入流中)。

$ cat ingredients
eggs
milk
butter
tomatoes
salt
$ sort ingredients
butter
eggs
milk
salt
tomatoes

sort -r 执行反向排序。

$ sort -r ingredients
tomatoes
salt
milk
eggs
butter

sort -n 按字段的算术值排序。

$ cat numbers
0
2
1
10
3
$ sort numbers
0
1
10
2
3
$ sort -n numbers
0
1
2
3
10

优衣库


uniq 检测并过滤指定文件或输入流中相邻的相同行。

$ cat duplicates
and one
and one
and two
and one
and two
and one, two, three
$ uniq duplicates
and one
and two
and one
and two
and one, two, three

由于它uniq仅过滤掉相邻的行,因此重复数据可能仍保留在我们的数据中。要从文件中过滤所有相同的行,必须首先对文件的内容进行排序。

$ sort duplicates | uniq
and one
and one, two, three
and two

uniq -c 在每一行的开头插入其出现的次数。

$ sort duplicates | uniq -c
   3 and one
   1 and one, two, three
   2 and two

uniq -u 仅显示唯一字符串。

$ sort duplicates | uniq -u
and one, two, three

注意。uniq它与排序结合使用时特别有用,因为管道| sort | uniq允许您删除文件或流中的所有重复行。

awk


awk-这不仅仅是文字处理工具:事实上,它具有完整的编程语言什么是awk 真正的好是分割文件转换成列,它有特殊的光彩做它时,空格和制表符的文件混合。

$ cat -t multi-columns
John Smith    Doctor^ITardis
Sarah-James Smith^I    Companion^ILondon
Rose Tyler   Companion^ILondon

注意。cat -t将标签显示为^I

如您所见,这些列由空格或制表符分隔,而不总是由相同数量的空格分隔。cut它在这里是无用的,因为它仅适用于一个分隔符。但是awk处理这样的文件很容易。

awk '{ print $n }'在文本中显示第n列。

$ cat multi-columns | awk '{ print $1 }'
John
Sarah-James
Rose
$ cat multi-columns | awk '{ print $3 }'
Doctor
Companion
Companion
$ cat multi-columns | awk '{ print $1,$2 }'
John Smith
Sarah-James Smith
Rose Tyler

尽管awk功能强大得多,但在我的个人案例中,扬声器的输出可能约为用例的99%。

注意。{ print $NF }显示一行中的最后一列。

TR


tr代表翻译此命令将一个字符替换为另一个字符。它适用于字符或字符类,例如小写,键入,空格,字母数字等。

在标准输入上,它将tr <char1> <char2>所有出现的<char1>替换为<char2>。

$ echo "Computers are fast" | tr a A
computers Are fAst

tr可以使用符号转换字符类[:class:]手册页上描述了可用类的完整列表tr,但此处进行了一些演示。

[:space:]代表所有类型的空格,从简单空格到制表符或换行符。

$ echo "computers are fast" | tr '[:space:]' ','
computers,are,fast,%

所有字符(如空格)均以逗号分隔。请注意,%输出末尾的字符表示不存在换行符。确实,此字符也转换为逗号。

[:lower:]代表所有小写字符和[:upper:] 所有大写字符因此,它们之间的转换变得微不足道。

$ echo "computers are fast" | tr '[:lower:]' '[:upper:]'
COMPUTERS ARE FAST
$ echo "COMPUTERS ARE FAST" | tr '[:upper:]' '[:lower:]'
computers are fast

tr -c SET1 SET2SET1中包含的任何字符转换为SET2中的字符。在以下示例中,除指示的元音外,所有其他字符均替换为空格。

$ echo "computers are fast" | tr -c '[aeiouy]' ' '
 o  u e   a e  a

tr -d删除指定的字符,但不替换它们。这是等效的tr <char> ''

$ echo "Computers Are Fast" | tr -d '[:lower:]'
C A F

tr也可以使用符号替换字符范围,例如ae之间所有字母或1和8之间的所有数字s-e,其中s 表示起始字符,e 表示结尾。

$ echo "computers are fast" | tr 'a-e' 'x'
xomputxrs xrx fxst
$ echo "5uch l337 5p34k" | tr '1-4' 'x'
5uch lxx7 5pxxk

该命令tr -s string1将所有多次出现的字符压缩为string1一个。最有用的用途之一tr -s是用一个替换多个连续的空格。

$ echo "Computers         are       fast" | tr -s ' '
Computers are fast


该命令将fold所有输入行折叠到指定的宽度。例如,确保文本适合在小显示器上显示可能很有用。因此,fold -w n堆叠宽度为n个字符的字符串。

$ cat ~/Documents/readme | fold -w 16
Thanks again for
 reading this bo
ok!
I hope you're fo
llowing so far!

该命令fold -s将仅在空格字符上换行。可以将其与前一个字符组合以将字符串限制为指定的字符数。

Thanks again
for reading
this book!
I hope you're
following so
far!

sed


sed是一种非交互式流编辑器,用于逐行转换输入流中的文本。作为输入,可以是文件或,或者stdin可以是输出处的文件或stdout

编辑器命令可以包括一个或多个地址函数参数因此,命令如下:

[address[,address]]function[arguments]

尽管它sed执行许多功能,但我们仅考虑将文本替换为最常见的用例之一。

文字替换


替换命令sed如下:

s/PATTERN/REPLACEMENT/[options]

示例:替换文件中每一行中单词的第一个实例:

$ cat hello
hello hello
hello world!
hi
$ cat hello | sed 's/hello/Hey I just met you/'
Hey I just met you hello
Hey I just met you world
hi

我们看到在第一行中只有第一个实例被替换hello要替换所有hello行中的所有匹配项,可以使用选项g(意味着global)。

$ cat hello | sed 's/hello/Hey I just met you/g'
Hey I just met you Hey I just met you
Hey I just met you world
hi

sed允许您使用除以外的任何定界符/,如果命令参数本身有斜杠,则可以特别提高可读性。

$ cat hello | sed 's@hello@Hey I just met you@g'
Hey I just met you Hey I just met you
Hey I just met you world
hi

地址告诉编辑者在哪一行或哪几行上执行替换。

$ cat hello | sed '1s/hello/Hey I just met you/g'
Hey I just met you hello
hello world
hi
$ cat hello | sed '2s/hello/Hey I just met you/g'
hello hello
Hey I just met you  world
hi

该地址在第一行中1表示替换为helloon Hey I just met you我们所用的符号指定地址的范围<start>,<end>,它<end>可以是行号或$,也就是说,在该文件中的最后一行。

$ cat hello | sed '1,2s/hello/Hey I just met you/g'
Hey I just met you Hey I just met you
Hey I just met you world
hi
$ cat hello | sed '2,3s/hello/Hey I just met you/g'
hello hello
Hey I just met you world
hi
$ cat hello | sed '2,$s/hello/Hey I just met you/g'
hello hello
Hey I just met you world
hi

默认情况下,它sed会自己产生结果stdout,但也可以使用option编辑原始文件-i

$ sed -i '' 's/hello/Bonjour/' sed-data
$ cat sed-data
Bonjour hello
Bonjour world
hi

注意。在Linux上,就足够了-i但是在macOS上,命令的行为略有不同,因此-i您需要在之后添加''

真实的例子


使用grep和awk进行CSV过滤


$ grep -w gauge metadata.csv | awk -F, '{ if ($4 == "query") { print $1, "per", $5 } }'
mysql.performance.com_delete per second
mysql.performance.com_delete_multi per second
mysql.performance.com_insert per second
mysql.performance.com_insert_select per second
mysql.performance.com_replace_select per second
mysql.performance.com_select per second
mysql.performance.com_update per second
mysql.performance.com_update_multi per second
mysql.performance.questions per second
mysql.performance.slow_queries per second
mysql.performance.queries per second

在此示例中grep,文件metadata.csv首先过滤包含单词的行gauge,然后过滤具有query第四列的行,并显示具有相应值per_unit_name(第五列)的度量标准名称(第一列)。

显示与网络接口关联的IPv4地址


$ ifconfig en0 | grep inet | grep -v inet6 | awk '{ print $2 }'
192.168.0.38

该命令ifconfig <interface name>在指定的网络接口上显示信息。例如:

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ether 19:64:92:de:20:ba
    inet6 fe80::8a3:a1cb:56ae:7c7c%en0 prefixlen 64 secured scopeid 0x7
    inet 192.168.0.38 netmask 0xffffff00 broadcast 192.168.0.255
    nd6 options=201<PERFORMNUD,DAD>
    media: autoselect
    status: active

然后运行grepinet,将产生对应的两行。

$ ifconfig en0 | grep inet
    inet6 fe80::8a3:a1cb:56ae:7c7c%en0 prefixlen 64 secured scopeid 0x7
    inet 192.168.0.38 netmask 0xffffff00 broadcast 192.168.0.255

然后,使用grep -v排除带有的行ipv6

$ ifconfig en0 | grep inet | grep -v inet6
inet 192.168.0.38 netmask 0xffffff00 broadcast 192.168.0.255

最后,在帮助下,我们awk请求该行的第二列:这是与我们的网络接口关联的IPv4地址en0

$ ifconfig en0 | grep inet | grep -v inet6 | awk '{ print $2 }'
192.168.0.38

注意。提供我的是grep inet | grep -v inet6一支如此可靠的团队awk

$ ifconfig en0 | awk ' $1 == "inet" { print $2 }'
192.168.0.38

它较短,专门针对带有条件的IPv4 $1 == "inet"

从配置文件中检索值


$ grep 'editor =' ~/.gitconfig  | cut -d = -f2 | sed 's/ //g'
/usr/bin/vim

在当前用户的git配置文件中,查找值editor =,裁剪字符=,提取第二列并删除周围的所有空格。

$ grep 'editor =' ~/.gitconfig
     editor = /usr/bin/vim
$ grep 'editor =' ~/.gitconfig  | cut -d'=' -f2
 /usr/bin/vim
$ grep 'editor =' ~/.gitconfig  | cut -d'=' -f2 | sed 's/ //'
/usr/bin/vim

从日志文件中提取IP


以下真实代码在数据库日志中查找消息Too many connections from(后跟IP地址),并显示十个主要入侵者。

$ grep 'Too many connections from' db.log | \
  awk '{ print $12 }' | \
  sed 's@/@@' | \
  sort | \
  uniq -c | \
  sort -rn | \
  head -n 10 | \
  awk '{ print $2 }'
   10.11.112.108
   10.11.111.70
   10.11.97.57
   10.11.109.72
   10.11.116.156
   10.11.100.221
   10.11.96.242
   10.11.81.68
   10.11.99.112
   10.11.107.120

让我们看看这个管道的作用。首先,日志中的行是什么样的。

$ grep "Too many connections from" db.log | head -n 1
2020-01-01 08:02:37,617 [myid:1] - WARN  [NIOServerCxn.Factory:1.2.3.4/1.2.3.4:2181:NIOServerCnxnFactory@193] - Too many connections from /10.11.112.108 - max is 60

然后awk '{ print $12 }'从字符串中提取IP地址。

$ grep "Too many connections from" db.log | awk '{ print $12 }'
/10.11.112.108
...

该命令sed 's@/@@'删除初始斜杠。

$ grep "Too many connections from" db.log | awk '{ print $12 }' | sed 's@/@@'
10.11.112.108
...

注意。如前所述,sed您可以在其中使用任何分隔符。尽管通常将其用作分隔符/,但在此我们将替换此特定字符,这将稍微削弱替换表达式的可读性。

sed 's/\///'

sort | uniq -c 按字典顺序对IP地址进行排序,然后删除重复项,并在每个IP地址之前添加条目数。

$ grep 'Too many connections from' db.log | \
  awk '{ print $12 }' | \
  sed 's@/@@' | \
  sort | \
  uniq -c
   1379 10.11.100.221
   1213 10.11.103.168
   1138 10.11.105.177
    946 10.11.106.213
   1211 10.11.106.4
   1326 10.11.107.120
   ...

sort -rn | head -n 10按出现次数对这些行进行排序,并按数字顺序和相反的顺序进行排列,以便首先显示主要违规者,其中显示10条行。最后一条命令awk { print $2 }本身检索IP地址。

$ grep 'Too many connections from' db.log | \
  awk '{ print $12 }' | \
  sed 's@/@@' | \
  sort | \
  uniq -c | \
  sort -rn | \
  head -n 10 | \
  awk '{ print $2 }'
  10.11.112.108
  10.11.111.70
  10.11.97.57
  10.11.109.72
  10.11.116.156
  10.11.100.221
  10.11.96.242
  10.11.81.68
  10.11.99.112
  10.11.107.120

在源文件中重命名功能


假设我们正在一个项目上,并且想在源文件中重命名该函数(或类,变量等)。您可以sed -i使用直接替换原始文件中的命令来执行此操作。

$ cat izk/utils.py
def bool_from_str(s):
    if s.isdigit():
        return int(s) == 1
    return s.lower() in ['yes', 'true', 'y']

$ sed -i 's/def bool_from_str/def is_affirmative/' izk/utils.py
$ cat izk/utils.py
def is_affirmative(s):
    if s.isdigit():
        return int(s) == 1
    return s.lower() in ['yes', 'true', 'y']

注意。在MacOS,sed -i使用代替sed -i ''

但是,我们仅在原始文件中重命名了该函数。由于bool_from_str不再定义此功能,因此这将中断其他文件的导入我们需要找到一种bool_from_str在整个项目中重命名的方法这可以使用命令grepsed循环for或使用来实现xargs

加深:周期forxargs


要替换项目中的所有事件bool_from_str,您必须首先使用递归查找它们grep -r

$ grep -r bool_from_str .
./tests/test_utils.py:from izk.utils import bool_from_str
./tests/test_utils.py:def test_bool_from_str(s, expected):
./tests/test_utils.py:    assert bool_from_str(s) == expected
./izk/utils.py:def bool_from_str(s):
./izk/prompt.py:from .utils import bool_from_str
./izk/prompt.py:                    default = bool_from_str(os.environ[envvar])

由于我们只对具有匹配项的文件感兴趣,因此您还必须使用选项-l/--files-with-matches

-l, --files-with-matches
        Only the names of files containing selected lines are written to standard out-
        put.  grep will only search a file until a match has been found, making
        searches potentially less expensive.  Pathnames are listed once per file
        searched.  If the standard input is searched, the string ``(standard input)''
        is written.

$ grep -r --files-with-matches bool_from_str .
./tests/test_utils.py
./izk/utils.py
./izk/prompt.py

然后,我们可以使用命令xargs从输出的每一行(即,包含line的所有文件bool_from_str)执行操作。

$ grep -r --files-with-matches bool_from_str . | \
  xargs -n 1 sed -i 's/bool_from_str/is_affirmative/'

该选项-n 1指示输出中的每一行应执行一个单独的命令sed

然后执行以下命令:

$ sed -i 's/bool_from_str/is_affirmative/' ./tests/test_utils.py
$ sed -i 's/bool_from_str/is_affirmative/' ./izk/utils.py
$ sed -i 's/bool_from_str/is_affirmative/' ./izk/prompt.py

如果您调用的命令xargs(在本例中为sed)支持多个参数,则应丢弃该参数-n 1以提高性能。

grep -r --files-with-matches bool_from_str . | xargs sed -i 's/bool_from_str/is_affirmative/'

然后将执行此命令

$ sed -i 's/bool_from_str/is_affirmative/' ./tests/test_utils.py ./izk/utils.py ./izk/prompt.py

注意。sed手册页上的提要中可以看出,该团队可以提出几个论点。

SYNOPSIS
     sed [-Ealn] command [file ...]
     sed [-Ealn] [-e command] [-f command_file] [-i extension] [file ...]

确实,正如我们在上一章中所看到的,这file ...意味着可以接受几个参数,即文件名。

我们看到,所有情况都被替换bool_from_str

$ grep -r is_affirmative .
./tests/test_utils.py:from izk.utils import is_affirmative
./tests/test_utils.py:def test_is_affirmative(s, expected):
./tests/test_utils.py:    assert is_affirmative(s) == expected
./izk/utils.py:def is_affirmative(s):
./izk/prompt.py:from .utils import is_affirmative
./izk/prompt.py:                    default = is_affirmative(os.environ[envvar])

通常,有几种方法可以达到相同的结果。相反,xargs我们可以使用循环for来遍历列表中的行,并对每个项目执行操作。这些循环具有以下语法:

for item in list; do
    command $item
done

如果我们总结我们的命令grep$(),那么shell将在执行其子shell,其结果将在随后的循环重复for

$ for file in $(grep -r --files-with-matches bool_from_str .); do
  sed -i 's/bool_from_str/is_affirmative/' $file
done

该命令将执行

$ sed -i 's/bool_from_str/is_affirmative/' ./tests/test_utils.py
$ sed -i 's/bool_from_str/is_affirmative/' ./izk/utils.py
$ sed -i 's/bool_from_str/is_affirmative/' ./izk/prompt.py

for我看来,循环语法比这更清晰xargs,但后者可以使用parameters并行执行命令-P n,其中,n是同时执行的最大并行命令数,这可以提高性能。

摘要


所有这些工具都为您带来了无限的可能性,因为它们使您能够提取和转换数据,从可能从未打算一起工作的团队中创建整个管道。它们每个都执行相对较小的功能(排序sort,合并cat,过滤器grep,编辑sed,剪切cut等)。

任何包含文本的任务都可以简化为一系列较小的任务,每个任务都执行一个简单的动作并将其输出传输到下一个任务。

例如,如果我们想知道日志文件中有多少个唯一IP地址,并且这些IP地址始终显示在同一列中,那么我们可以运行以下命令序列:

  • grep 与IP地址的字符串模式匹配的字符串
  • 找到具有IP地址的列,将其提取出来 awk
  • 使用以下命令对IP地址列表进行排序 sort
  • 消除相邻重复项 uniq
  • 计算行数(即唯一的IP地址),使用 wc -l

由于有许多本机和第三方文字处理工具,因此也有许多方法可以解决任何问题。

本文中的示例牵强一些,但我建议您阅读精彩的文章`` 命令行工具可以比Hadoop集群快235倍'',以了解这些命令的真正有用性和强大性以及真正的问题他们可以决定。

下一步是什么


  1. 计算位于您的主目录中的文件和目录的数量。
  2. .
  3. , .
  4. . .



« » (Essential Tools and Practices for the Aspiring Software Developer) , . , , , , git, SQL, Make, jq , , .

, !

All Articles