Linux 中 cut 命令的 4 个基本实用用法

cut 命令是从文本文件中删除“列”的规范工具。 在这种情况下,“列”可以定义为由字符或字节在行上的物理位置标识的一系列字符或字节,或由分隔符分隔的字段范围。

我之前写过关于使用 AWK 命令的文章。 在这个详细的指南中,我将解释 Linux 中 cut 命令的四个基本且实用的示例,它们将帮助您大有作为。

4 Linux中Cut命令的实际例子

如果您愿意,可以观看此视频,其中解释了我在文章中列出的相同的 cut 命令的实际示例。

1. 使用字符范围

当用 -c 命令行选项,cut 命令将删除 特点 范围。

与任何其他过滤器一样,cut 命令不会就地更改输入文件,但会将修改后的数据复制到其标准输出。 您有责任将命令输出重定向到文件以保存结果或使用管道将其作为输入发送到另一个命令。

如果你已经下载了 示例测试文件 在上面的视频中使用,您可以看到 BALANCE.txt 数据文件,直接来自我妻子在工作中使用的会计软件:

sh$ head BALANCE.txt
ACCDOC    ACCDOCDATE    ACCOUNTNUM ACCOUNTLIB              ACCDOCLIB                        DEBIT          CREDIT
4         1012017       623477     TIDE SCHEDULE           ALNEENRE-4701-LOC                00000001615,00
4         1012017       445452     VAT BS/ENC              ALNEENRE-4701-LOC                00000000323,00
4         1012017       4356       PAYABLES                ALNEENRE-4701-LOC                               00000001938,00
5         1012017       623372     ACCOMODATION GUIDE      ALNEENRE-4771-LOC                00000001333,00
5         1012017       445452     VAT BS/ENC              ALNEENRE-4771-LOC                00000000266,60
5         1012017       4356       PAYABLES                ALNEENRE-4771-LOC                               00000001599,60
6         1012017       4356       PAYABLES                FACT FA00006253 - BIT QUIROBEN                  00000001837,20
6         1012017       445452     VAT BS/ENC              FACT FA00006253 - BIT QUIROBEN   00000000306,20
6         1012017       623795     TOURIST GUIDE BOOK      FACT FA00006253 - BIT QUIROBEN   00000001531,00

这是一个固定宽度的文本文件,因为数据字段用可变数量的空格填充,以确保它们显示为一个很好对齐的表格。

作为推论,数据列始终在每行的相同字符位置开始和结束。 但是有一个小陷阱:尽管它的名字, cut 命令实际上要求您指定要保留的数据范围,而不是要删除的范围。 所以,如果我只需要 ACCOUNTNUMACCOUNTLIB 上面数据文件中的列,我会这样写:

sh$ cut -c 25-59 BALANCE.txt | head
ACCOUNTNUM ACCOUNTLIB
623477     TIDE SCHEDULE
445452     VAT BS/ENC
4356       /accountPAYABLES
623372     ACCOMODATION GUIDE
445452     VAT BS/ENC
4356       PAYABLES
4356       PAYABLES
445452     VAT BS/ENC
623795     TOURIST GUIDE BOOK

什么是范围?

正如我们刚刚看到的,cut 命令要求我们指定要保留的数据范围。 那么,让我们更正式地介绍什么是范围:对于 cut 命令,范围由以连字符分隔的开始和结束位置定义。 范围是从 1 开始的,即该行的第一项是项目编号 1,而不是 0。范围是包括在内的:开始和结束将保留在输出中,以及它们之间的所有字符。 指定结束位置在其开始位置之前(“低于”)的范围是错误的。 作为一种快捷方式,您可以省略开始或结束值,如下表所述:

  • a-b: a 和 b 之间的范围(含)
  • a: 相当于范围 a-a
  • -b: 相当于 1-a
  • b-: 相当于 b-∞

cut 命令允许您通过用逗号分隔来指定多个范围。 下面是几个例子:

# Keep characters from 1 to 24 (inclusive)
cut -c -24 BALANCE.txt

# Keep characters from 1 to 24 and 36 to 59 (inclusive)
cut -c -24,36-59 BALANCE.txt

# Keep characters from 1 to 24, 36 to 59 and 93 to the end of the line (inclusive)
cut -c -24,36-59,93- BALANCE.txt

的一个限制(或功能,取决于您看待它的方式) cut 命令是它永远不会重新排序数据。 因此,尽管范围以不同的顺序指定,以下命令将产生与前一个完全相同的结果:

cut -c 93-,-24,36-59 BALANCE.txt

您可以使用 diff 命令:

diff -s <(cut -c -24,36-59,93- BALANCE.txt) 
              <(cut -c 93-,-24,36-59 BALANCE.txt)
Files /dev/fd/63 and /dev/fd/62 are identical

同样, cut 命令从不复制数据:

# One might expect that could be a way to repeat
# the first column three times, but no...
cut -c -10,-10,-10 BALANCE.txt | head -5
ACCDOC
4
4
4
5

值得一提的是,有一项提议 -o 取消最后两个限制的选项,允许 cut 用于重新排序或复制数据的实用程序。 但这是 被 POSIX 委员会拒绝“因为这种类型的增强超出了 IEEE P1003.2b 标准草案的范围。”

就我个人而言,我不知道有任何削减版本将该提案作为扩展来实施。 但是,如果您这样做了,请使用评测部分与我们分享!

2. 使用字节范围

当用 -b 命令行选项,cut 命令将删除 字节 范围。

乍一看,字符范围和字节范围没有明显区别:

sh$ diff -s <(cut -b -24,36-59,93- BALANCE.txt) 
              <(cut -c -24,36-59,93- BALANCE.txt)
Files /dev/fd/63 and /dev/fd/62 are identical

那是因为我的示例数据文件正在使用 US-ASCII 字符编码 (“字符集”)作为 file -i 命令可以正确猜测它:

sh$ file -i BALANCE.txt
BALANCE.txt: text/plain; charset=us-ascii

在该字符编码中,字符和字节之间存在一对一的映射。 仅使用一个字节,理论上您最多可以编码 256 个不同的字符(数字、字母、标点、符号……)实际上,这个数字要低得多,因为字符编码为一些特殊值(如 32 或 65 控制字符 一般发现)。 无论怎样,即使我们可以使用完整的字节范围,也远远不足以存储人类书写的多样性。 所以,今天,字符和字节之间的一对一映射比常态更例外,几乎总是被无处不在的 UTF-8 多字节编码所取代。 现在让我们看看 cut 命令怎样处理它。

使用多字节字符

正如我之前所说,用作该文章示例的示例数据文件来自我妻子使用的会计软件。 它附加了她最近更新了该软件,之后,导出的文本文件略有不同。 我让你尝试自己发现差异:

sh$ head BALANCE-V2.txt
ACCDOC    ACCDOCDATE    ACCOUNTNUM ACCOUNTLIB              ACCDOCLIB                        DEBIT          CREDIT
4         1012017       623477     TIDE SCHEDULE           ALNÉENRE-4701-LOC                00000001615,00
4         1012017       445452     VAT BS/ENC              ALNÉENRE-4701-LOC                00000000323,00
4         1012017       4356       PAYABLES                ALNÉENRE-4701-LOC                               00000001938,00
5         1012017       623372     ACCOMODATION GUIDE      ALNÉENRE-4771-LOC                00000001333,00
5         1012017       445452     VAT BS/ENC              ALNÉENRE-4771-LOC                00000000266,60
5         1012017       4356       PAYABLES                ALNÉENRE-4771-LOC                               00000001599,60
6         1012017       4356       PAYABLES                FACT FA00006253 - BIT QUIROBEN                  00000001837,20
6         1012017       445452     VAT BS/ENC              FACT FA00006253 - BIT QUIROBEN   00000000306,20
6         1012017       623795     TOURIST GUIDE BOOK      FACT FA00006253 - BIT QUIROBEN   00000001531,00

本节的标题可能会帮助您找到发生了哪些变化。 但是,无论是否找到,现在让我们看看这种变化的后果:

sh$ cut -c 93-,-24,36-59 BALANCE-V2.txt
ACCDOC    ACCDOCDATE    ACCOUNTLIB              DEBIT          CREDIT
4         1012017       TIDE SCHEDULE            00000001615,00
4         1012017       VAT BS/ENC               00000000323,00
4         1012017       PAYABLES                                00000001938,00
5         1012017       ACCOMODATION GUIDE       00000001333,00
5         1012017       VAT BS/ENC               00000000266,60
5         1012017       PAYABLES                                00000001599,60
6         1012017       PAYABLES                               00000001837,20
6         1012017       VAT BS/ENC              00000000306,20
6         1012017       TOURIST GUIDE BOOK      00000001531,00
19        1012017       SEMINAR FEES            00000000080,00
19        1012017       PAYABLES                               00000000080,00
28        1012017       MAINTENANCE             00000000746,58
28        1012017       VAT BS/ENC              00000000149,32
28        1012017       PAYABLES                               00000000895,90
31        1012017       PAYABLES                                00000000240,00
31        1012017       VAT BS/DEBIT             00000000040,00
31        1012017       S           00000000200,00
32        1012017       WATER                   00000000202,20
32        1012017       VAT BS/DEBIT            00000000020,22
32        1012017       WATER                   00000000170,24
32        1012017       VAT BS/DEBIT            00000000009,37
32        1012017       PAYABLES                               00000000402,03
34        1012017       RENTAL COSTS            00000000018,00
34        1012017       PAYABLES                               00000000018,00
35        1012017       MISCELLANEOUS CHARGES   00000000015,00
35        1012017       VAT BS/DEBIT            00000000003,00
35        1012017       PAYABLES                               00000000018,00
36        1012017       LANDLINE TELEPHONE        00000000069,14
36        1012017       VAT BS/ENC                00000000013,83

我已经在 in-extenso 的命令输出上方复制了,所以很明显列对齐出了问题。

解释是原始数据文件只包含 US-ASCII 字符(符号、标点、数字和拉丁字母,没有任何变音符号)

但是,如果您仔细查看软件更新后生成的文件,您会发现新的导出数据文件现在保留了重音字母。 为了 example,名为“ALNÉENRE”的公司现在拼写正确,而以前出口为“ALNEENRE”(无重音)

file -i 实用程序没有错过该更改,因为它现在报告文件为 UTF-8 编码

sh$ file -i BALANCE-V2.txt
BALANCE-V2.txt: text/plain; charset=utf-8

要查看 UTF-8 文件中重音字母的编码方式,我们可以使用 hexdump 允许我们直接查看文件中字节的实用程序:

# To reduce clutter, let's focus only on the second line of the file
sh$ sed '2!d' BALANCE-V2.txt
4         1012017       623477     TIDE SCHEDULE           ALNÉENRE-4701-LOC                00000001615,00
sh$ sed '2!d' BALANCE-V2.txt  | hexdump -C
00000000  34 20 20 20 20 20 20 20  20 20 31 30 31 32 30 31  |4         101201|
00000010  37 20 20 20 20 20 20 20  36 32 33 34 37 37 20 20  |7       623477  |
00000020  20 20 20 54 49 44 45 20  53 43 48 45 44 55 4c 45  |   TIDE SCHEDULE|
00000030  20 20 20 20 20 20 20 20  20 20 20 41 4c 4e c3 89  |           ALN..|
00000040  45 4e 52 45 2d 34 37 30  31 2d 4c 4f 43 20 20 20  |ENRE-4701-LOC   |
00000050  20 20 20 20 20 20 20 20  20 20 20 20 20 30 30 30  |             000|
00000060  30 30 30 30 31 36 31 35  2c 30 30 20 20 20 20 20  |00001615,00     |
00000070  20 20 20 20 20 20 20 20  20 20 20 0a              |           .|
0000007c

在 00000030 的线路上 hexdump 输出,在一堆空格之后(字节 20),你可以看到:

  • A 被编码为字节 41,
  • L 被编码为字节 4c,
  • 和信 N 被编码为字节 4e.

但是,大写 带有 ACUTE 的拉丁文大写字母 E (因为它是 Unicode 标准中字母 É 的正式名称)使用两个字节进行编码 c3 89

这就是问题所在:使用 cut 范围表示为字节位置的命令适用于固定长度编码,但不适用于可变长度编码,如 UTF-8 或 移位 JIS. 这在下面有清楚的解释 POSIX 标准的非规范性摘录

早期版本的 cut 实用程序在字节和字符被认为是等效的环境中工作(在某些实现中模 处理)。 在多字节字符的扩展世界中,添加了新的 -b 选项。

嘿,等一下! 我没有使用 -b “故障”中的选项 example 以上,但 -c 选项。 所以,这不应该奏效吗?!?

是的,它应该:这是不幸的,但我们在 2018 年,尽管如此,从 GNU Coreutils 8.30 开始,cut 实用程序的 GNU 实现仍然不能正确处理多字节字符。 引用 GNU 文档, 这 -c 选项是“目前与 -b 相同,但国际化将改变这一点[… ]”——10 多年以来一直存在的提及!

另一方面, 开放式BSD cut 实用程序的实现符合 POSIX 标准,并将遵循当前的语言环境设置以正确处理多字节字符:

# Ensure subseauent commands will know we are using UTF-8 encoded
# text files
openbsd-6.3$ export LC_CTYPE=en_US.UTF-8

# With the `-c` option, cut works properly with multi-byte characters
openbsd-6.3$ cut -c -24,36-59,93- BALANCE-V2.txt
ACCDOC    ACCDOCDATE    ACCOUNTLIB              DEBIT          CREDIT
4         1012017       TIDE SCHEDULE           00000001615,00
4         1012017       VAT BS/ENC              00000000323,00
4         1012017       PAYABLES                               00000001938,00
5         1012017       ACCOMODATION GUIDE      00000001333,00
5         1012017       VAT BS/ENC              00000000266,60
5         1012017       PAYABLES                               00000001599,60
6         1012017       PAYABLES                               00000001837,20
6         1012017       VAT BS/ENC              00000000306,20
6         1012017       TOURIST GUIDE BOOK      00000001531,00
19        1012017       SEMINAR FEES            00000000080,00
19        1012017       PAYABLES                               00000000080,00
28        1012017       MAINTENANCE             00000000746,58
28        1012017       VAT BS/ENC              00000000149,32
28        1012017       PAYABLES                               00000000895,90
31        1012017       PAYABLES                               00000000240,00
31        1012017       VAT BS/DEBIT            00000000040,00
31        1012017       S          00000000200,00
32        1012017       WATER                   00000000202,20
32        1012017       VAT BS/DEBIT            00000000020,22
32        1012017       WATER                   00000000170,24
32        1012017       VAT BS/DEBIT            00000000009,37
32        1012017       PAYABLES                               00000000402,03
34        1012017       RENTAL COSTS            00000000018,00
34        1012017       PAYABLES                               00000000018,00
35        1012017       MISCELLANEOUS CHARGES   00000000015,00
35        1012017       VAT BS/DEBIT            00000000003,00
35        1012017       PAYABLES                               00000000018,00
36        1012017       LANDLINE TELEPHONE      00000000069,14
36        1012017       VAT BS/ENC              00000000013,83

正如预期的那样,当使用 -b 字节模式而不是 -c 字符模式,OpenBSD cut 实现的行为就像传统的 cut

openbsd-6.3$ cut -b -24,36-59,93- BALANCE-V2.txt
ACCDOC    ACCDOCDATE    ACCOUNTLIB              DEBIT          CREDIT
4         1012017       TIDE SCHEDULE            00000001615,00
4         1012017       VAT BS/ENC               00000000323,00
4         1012017       PAYABLES                                00000001938,00
5         1012017       ACCOMODATION GUIDE       00000001333,00
5         1012017       VAT BS/ENC               00000000266,60
5         1012017       PAYABLES                                00000001599,60
6         1012017       PAYABLES                               00000001837,20
6         1012017       VAT BS/ENC              00000000306,20
6         1012017       TOURIST GUIDE BOOK      00000001531,00
19        1012017       SEMINAR FEES            00000000080,00
19        1012017       PAYABLES                               00000000080,00
28        1012017       MAINTENANCE             00000000746,58
28        1012017       VAT BS/ENC              00000000149,32
28        1012017       PAYABLES                               00000000895,90
31        1012017       PAYABLES                                00000000240,00
31        1012017       VAT BS/DEBIT             00000000040,00
31        1012017       S           00000000200,00
32        1012017       WATER                   00000000202,20
32        1012017       VAT BS/DEBIT            00000000020,22
32        1012017       WATER                   00000000170,24
32        1012017       VAT BS/DEBIT            00000000009,37
32        1012017       PAYABLES                               00000000402,03
34        1012017       RENTAL COSTS            00000000018,00
34        1012017       PAYABLES                               00000000018,00
35        1012017       MISCELLANEOUS CHARGES   00000000015,00
35        1012017       VAT BS/DEBIT            00000000003,00
35        1012017       PAYABLES                               00000000018,00
36        1012017       LANDLINE TELEPHONE        00000000069,14
36        1012017       VAT BS/ENC                00000000013,83

3. 使用字段

从某种意义上说,使用分隔文本文件中的字段对 cut 实用程序,因为它只需要在每一行上定位(一个字节)字段分隔符,然后将字段内容逐字复制到输出,而无需担心任何编码问题。

这是一个带分隔符的文本文件示例:

sh$ head BALANCE.csv
ACCDOC;ACCDOCDATE;ACCOUNTNUM;ACCOUNTLIB;ACCDOCLIB;DEBIT;CREDIT
4;1012017;623477;TIDE SCHEDULE;ALNEENRE-4701-LOC;00000001615,00;
4;1012017;445452;VAT BS/ENC;ALNEENRE-4701-LOC;00000000323,00;
4;1012017;4356;PAYABLES;ALNEENRE-4701-LOC;;00000001938,00
5;1012017;623372;ACCOMODATION GUIDE;ALNEENRE-4771-LOC;00000001333,00;
5;1012017;445452;VAT BS/ENC;ALNEENRE-4771-LOC;00000000266,60;
5;1012017;4356;PAYABLES;ALNEENRE-4771-LOC;;00000001599,60
6;1012017;4356;PAYABLES;FACT FA00006253 - BIT QUIROBEN;;00000001837,20
6;1012017;445452;VAT BS/ENC;FACT FA00006253 - BIT QUIROBEN;00000000306,20;
6;1012017;623795;TOURIST GUIDE BOOK;FACT FA00006253 - BIT QUIROBEN;00000001531,00;

您可能知道该文件格式为 CSV文件 (对于逗号分隔值),即使字段分隔符并不总是逗号。 为了 example, 分号 (;) 作为字段分隔符经常遇到,并且在已经使用逗号作为分隔符的国家/地区将数据导出为“CSV”时,它通常是默认选择 小数点分隔符 (就像我们在法国所做的那样——因此在我的示例文件中选择了那个字符)。 另一个流行的变体使用 制表符 作为字段分隔符,产生有时称为 制表符分隔值 文件。 最后,在 Unix 和 Linux 世界中,冒号 (:) 是您可能会发现的另一个相对常见的字段分隔符,例如 example, 在标准 /etc/passwd/etc/group 文件。

使用带分隔符的文本文件格式时,您向 cut 命令提供字段范围以继续使用 -f 选项,您必须使用 -d 选项(没有 -d 选项,cut 实用程序默认为分隔符的制表符):

sh$ cut -f 5- -d';' BALANCE.csv | head
ACCDOCLIB;DEBIT;CREDIT
ALNEENRE-4701-LOC;00000001615,00;
ALNEENRE-4701-LOC;00000000323,00;
ALNEENRE-4701-LOC;;00000001938,00
ALNEENRE-4771-LOC;00000001333,00;
ALNEENRE-4771-LOC;00000000266,60;
ALNEENRE-4771-LOC;;00000001599,60
FACT FA00006253 - BIT QUIROBEN;;00000001837,20
FACT FA00006253 - BIT QUIROBEN;00000000306,20;
FACT FA00006253 - BIT QUIROBEN;00000001531,00;

处理不包含分隔符的行

但是如果输入文件中的某些行不包含分隔符怎么办? 很容易将其想象为仅包含第一个字段的行。 但这不是 cut 实用程序的作用。

默认情况下,当使用 -f 选项,cut 实用程序将始终逐字输出不包含分隔符的行(可能假设这是一个非数据行,如标题或某种注释):

sh$ (echo "# 2018-03 BALANCE"; cat BALANCE.csv) > BALANCE-WITH-HEADER.csv

sh$ cut -f 6,7 -d';' BALANCE-WITH-HEADER.csv | head -5
# 2018-03 BALANCE
DEBIT;CREDIT
00000001615,00;
00000000323,00;
;00000001938,00

使用 -s 选项,你可以扭转这种行为,所以 cut 将始终忽略这样的行:

sh$ cut -s -f 6,7 -d';' BALANCE-WITH-HEADER.csv | head -5
DEBIT;CREDIT
00000001615,00;
00000000323,00;
;00000001938,00
00000001333,00;

如果您心情不好,您可以利用该功能作为一种相对晦涩的方式来仅保留包含给定字符的行:

# Keep lines containing a `e`
sh$ printf "%sn" {mighty,bold,great}-{condor,monkey,bear} | cut -s -f 1- -d'e'

更改输出分隔符

作为扩展,cut 的 GNU 实现允许使用不同的字段分隔符作为输出使用 --output-delimiter 选项:

sh$ cut -f 5,6- -d';' --output-delimiter="*" BALANCE.csv | head
ACCDOCLIB*DEBIT*CREDIT
ALNEENRE-4701-LOC*00000001615,00*
ALNEENRE-4701-LOC*00000000323,00*
ALNEENRE-4701-LOC**00000001938,00
ALNEENRE-4771-LOC*00000001333,00*
ALNEENRE-4771-LOC*00000000266,60*
ALNEENRE-4771-LOC**00000001599,60
FACT FA00006253 - BIT QUIROBEN**00000001837,20
FACT FA00006253 - BIT QUIROBEN*00000000306,20*
FACT FA00006253 - BIT QUIROBEN*00000001531,00*

请注意,在这种情况下,所有出现的字段分隔符都将被替换,而不仅仅是在命令行参数中指定的范围边界处的那些。

4. 非 POSIX GNU 扩展

说到非 POSIX GNU 扩展,其中一些特别有用。 值得一提的是,以下扩展同样适用于字节、字符(对于当前 GNU 实现中的含义)或字段范围:--complement

将该选项视为 sed 地址中的感叹号(!); 而不是保持数据匹配给定的范围, cut 将保持数据不匹配范围

# Keep only field 5
sh$ cut -f 5 -d';' BALANCE.csv |head -3
ACCDOCLIB
ALNEENRE-4701-LOC
ALNEENRE-4701-LOC

# Keep all but field 5
sh$ cut --complement -f 5 -d';' BALANCE.csv |head -3
ACCDOC;ACCDOCDATE;ACCOUNTNUM;ACCOUNTLIB;DEBIT;CREDIT
4;1012017;623477;TIDE SCHEDULE;00000001615,00;
4;1012017;445452;VAT BS/ENC;00000000323,00;

--zero-terminated (-z)

使用 空字符 作为行终止符而不是 换行符. 这 -z 当您的数据可能包含嵌入的换行符时,选项特别有用,例如处理文件名时(因为换行符是文件名中的有效字符,但 NUL 不是)。

向您展示怎样 -z 选项有效,让我们做一个小实验。 首先,我们将创建一个文件,其名称包含嵌入的新行:

bash$ touch

现在假设我想显示每个字符的前 5 个字符 *.txt 文档名称。 一个天真的解决方案将在这里惨遭失败:

sh$ ls -1 *.txt | cut -c 1-5
BALAN
BALAN
EMPTY
FILE
WITH
NAME.

你可能已经读过 ls 专为 人类消费,并且在命令管道中使用它是一种反模式(确实如此)。 所以让我们使用 find 命令改为:

sh$ find . -name '*.txt' -printf "%fn" | cut -c 1-5
BALAN
EMPTY
FILE
WITH
NAME.
BALAN

并且……产生了与以前基本相同的错误结果(尽管顺序不同,因为 ls 隐式排序文件名, find 命令不执行)。

问题是在这两种情况下, cut 命令无法区分作为数据字段(文件名)一部分的换行符和用作记录结束标记的换行符。 但是,使用 NUL 字节() 作为行终止符清除了混乱,因此我们最终可以获得预期的结果:

# I was told (?) some old versions of tr require using 00 instead of 
# to denote the NUL character (let me know if you needed that change!)
sh$ find . -name '*.txt' -printf "%f" | cut -z -c 1-5| tr '' 'n'
BALAN
EMPTY
BALAN

有了那个最新的 example,我们正在远离本文的核心 cut 命令。 所以,我会让你试着自己弄清楚时髦的含义 "%f" 之后 -printf 的论证 find 命令或我为什么使用 tr 命令在管道的末尾。

使用 Cut 命令可以完成更多工作

我只是展示了最常见的,在我看来也是最重要的 Cut 命令的用法。 您可以以更实用的方式应用该命令。 这取决于你的逻辑推理和想象力。

不要犹豫,使用下面的评测部分发布您的发现。 而且,一如既往,如果您喜欢这篇文章,请不要忘记在您最喜欢的网站和社交媒体上分享它!

相关阅读:

Posted in: Linux