• [高清组图]环广西赛:参赛车队赛前适应训练 2018-08-31
  • [高清组图]特谢拉复出吴曦失单刀 苏宁0-0平斯威 2018-08-31
  • [高清组图]潜水偶遇座头鲸 亲密互动玩起“水中击掌” 2018-08-31
  • [高清组图]法拉利拍定妆照 维特尔KIMI准备好了 2018-08-31
  • [高清组图]毛剑卿伤退莫雷诺捅射 申花1-0一方 2018-08-31
  • [高清组图]比埃拉双响巴坎布建功 国安5-1富力 2018-08-31
  • [高清组图]武磊世界波胡尔克点射 上港2-0胜申花 2018-08-31
  • [高清组图]武磊2球吕文君建功 上港3-1富力 2018-08-31
  • [高清组图]欧超杯-科斯塔2球 皇马加时赛2-4马竞 2018-08-31
  • [高清组图]格里芬赤膊骑行 休赛期享受二人世界 2018-08-31
  • [视频]【深化改革 重在实效】精准扶贫 四川彝区要拔掉“穷根” 2018-08-31
  • [视频]【深化改革 重在实效】破藩篱促合力 体制创新粘合“两张皮” 2018-08-31
  • [视频]【深化改革 重在实效】激发活力 实现市场准入全程便利化 2018-08-31
  • [视频]【深化改革 重在实效】打通简政放权的“最后一公里” 2018-08-31
  • [视频]【深化改革 重在实效】广东:户籍改革为外来工打开一扇门 2018-08-31
  • 手机版
    你好,游客 登录 注册 搜索
    背景:
    阅读新闻

    Linux 下 cut 命令的 4 个基础实用的示例

    [日期:2018-08-15] 来源:Linux中国  作者:Linux [字体: ]

    奥门新萄京官方正版 www.arianalance.com

    cut 命令是用来从文本文件中移除“某些列”的经典工具。在本文中的“一列”可以被定义为按照一行中位置区分的一系列字符串或者字节,或者是以某个分隔符为间隔的某些域。

    在本文中,我将解释 linux 下 cut 命令的 4 个本质且实用的例子,有时这些例子将帮你节省很多时间。

     

    Linux 下 cut 命令的 4 个实用示例

    假如你想,你可以观看下面的视频,视频中解释了本文中我列举的 cut 命令的使用例子。

     

    1、 作用在一系列字符上

    当启用 -c 命令行选项时,cut 命令将移除一系列字符。

    和其他的过滤器类似, cut 命令不会直接改变输入的文件,它将复制已修改的数据到它的标准输出里去。你可以通过重定向命令的结果到一个文件中来保存修改后的结果,或者使用管道将结果送到另一个命令的输入中,这些都由你来负责。

    假如你已经下载了上面视频中的示例测试文件,你将看到一个名为 BALANCE.txt 的数据文件,这些数据是直接从我妻子在她工作中使用的某款会计软件中导出的:

    1. sh$ head BALANCE.txt
    2. ACCDOC ACCDOCDATE ACCOUNTNUM ACCOUNTLIB ACCDOCLIB DEBIT CREDIT
    3. 41012017623477 TIDE SCHEDULE ALNEENRE-4701-LOC 00000001615,00
    4. 41012017445452 VAT BS/ENC ALNEENRE-4701-LOC 00000000323,00
    5. 410120174356 PAYABLES ALNEENRE-4701-LOC 00000001938,00
    6. 51012017623372 ACCOMODATION GUIDE ALNEENRE-4771-LOC 00000001333,00
    7. 51012017445452 VAT BS/ENC ALNEENRE-4771-LOC 00000000266,60
    8. 510120174356 PAYABLES ALNEENRE-4771-LOC 00000001599,60
    9. 610120174356 PAYABLES FACT FA00006253 - BIT QUIROBEN 00000001837,20
    10. 61012017445452 VAT BS/ENC FACT FA00006253 - BIT QUIROBEN 00000000306,20
    11. 61012017623795 TOURIST GUIDE BOOK FACT FA00006253 - BIT QUIROBEN 00000001531,00

    上述文件是一个固定宽度的文本文件,因为对于每一项数据,都使用了不定长的空格做填充,使得它看起来是一个对齐的列表。

    这样一来,每一列数据开始和结束的位置都是一致的。从 cut 命令的字面意思去理解会给我们带来一个小陷阱:cut 命令实际上需要你指出你想保留的数据范围,而不是你想移除的范围。所以,假如我需要上面文件中的 ACCOUNTNUMACCOUNTLIB 列,我需要这么做:

    1. sh$ cut-c 25-59 BALANCE.txt |head
    2. ACCOUNTNUM ACCOUNTLIB
    3. 623477 TIDE SCHEDULE
    4. 445452 VAT BS/ENC
    5. 4356/accountPAYABLES
    6. 623372 ACCOMODATION GUIDE
    7. 445452 VAT BS/ENC
    8. 4356 PAYABLES
    9. 4356 PAYABLES
    10. 445452 VAT BS/ENC
    11. 623795 TOURIST GUIDE BOOK

     

    范围如何定义?

    正如我们上面看到的那样, cut 命令需要我们特别指定需要保留的数据的范围。所以,下面我将更正式地介绍如何定义范围:对于 cut 命令来说,范围是由连字符(-)分隔的起始和结束位置组成,范围是基于 1 计数的,即每行的第一项是从 1 开始计数的,而不是从 0 开始。范围是一个闭区间,开始和结束位置都将包含在结果之中,正如它们之间的所有字符那样。如果范围中的结束位置比起始位置小,则这种表达式是错误的。作为快捷方式,你可以省略起始结束值,正如下面的表格所示:

    < 如显示不全,请左右滑动 >

    范围含义
    a-b a 和 b 之间的范围(闭区间)
    a 与范围 a-a 等价
    -b 与范围 1-a 等价
    b- 与范围 b-∞ 等价

    cut 命令允许你通过逗号分隔多个范围,下面是一些示例:

    1. #保留124之间(闭区间)的字符
    2. cut-c -24 BALANCE.txt
    3. #保留124(闭区间)以及3659(闭区间)之间的字符
    4. cut-c -24,36-59 BALANCE.txt
    5. #保留124(闭区间)、3659(闭区间)和93到该行末尾之间的字符
    6. cut-c -24,36-59,93- BALANCE.txt

    cut 命令的一个限制(或者是特性,取决于你如何看待它)是它将 不会对数据进行重排。所以下面的命令和先前的命令将产生相同的结果,尽管范围的顺序做了改变:

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

    你可以轻易地使用 diff 命令来验证:

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

    类似的,cut 命令 不会重复数据

    1. #某人或许期待这可以第一列三次,但并不会……
    2. cut-c -10,-10,-10 BALANCE.txt |head-5
    3. ACCDOC
    4. 4
    5. 4
    6. 4
    7. 5

    值得提及的是,曾经有一个提议,建议使用 -o 选项来去除上面提到的两个限制,使得 cut 工具可以重排或者重复数据。但这个提议被 POSIX 委员会拒绝了“因为这类增强不属于 IEEE P1003.2b 草案标准的范围”

    据我所知,我还没有见过哪个版本的 cut 程序实现了上面的提议,以此来作为扩展,假如你知道某些例外,请使用下面的评论框分享给大家!

     

    2、 作用在一系列字节上

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

    咋一看,使用字符范围和使用字节没有什么明显的不同:

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

    这是因为我们的示例数据文件使用的是 US-ASCII 编码(字符集),使用 file -i 便可以正确地猜出来:

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

    在 US-ASCII 编码中,字符和字节是一一对应的。理论上,你只需要使用一个字节就可以表示 256 个不同的字符(数字、字母、标点符号和某些符号等)。实际上,你能表达的字符数比 256 要更少一些,因为字符编码中为某些特定值做了规定(例如 32 或 65 就是控制字符)。即便我们能够使用上述所有的字节范围,但对于存储种类繁多的人类手写符号来说,256 是远远不够的。所以如今字符和字节间的一一对应更像是某种例外,并且几乎总是被无处不在的 UTF-8 多字节编码所取代。下面让我们看看如何来处理多字节编码的情形。

     

    作用在多字节编码的字符上

    正如我前面提到的那样,示例数据文件来源于我妻子使用的某款会计软件。最近好像她升级了那个软件,然后呢,导出的文本就完全不同了,你可以试试和上面的数据文件相比,找找它们之间的区别:

    1. sh$ head BALANCE-V2.txt
    2. ACCDOC ACCDOCDATE ACCOUNTNUM ACCOUNTLIB ACCDOCLIB DEBIT CREDIT
    3. 41012017623477 TIDE SCHEDULE ALNÉENRE-4701-LOC 00000001615,00
    4. 41012017445452 VAT BS/ENC ALNÉENRE-4701-LOC 00000000323,00
    5. 410120174356 PAYABLES ALNÉENRE-4701-LOC 00000001938,00
    6. 51012017623372 ACCOMODATION GUIDE ALNÉENRE-4771-LOC 00000001333,00
    7. 51012017445452 VAT BS/ENC ALNÉENRE-4771-LOC 00000000266,60
    8. 510120174356 PAYABLES ALNÉENRE-4771-LOC 00000001599,60
    9. 610120174356 PAYABLES FACT FA00006253 - BIT QUIROBEN 00000001837,20
    10. 61012017445452 VAT BS/ENC FACT FA00006253 - BIT QUIROBEN 00000000306,20
    11. 61012017623795 TOURIST GUIDE BOOK FACT FA00006253 - BIT QUIROBEN 00000001531,00

    上面的标题栏或许能够帮助你找到什么被改变了,但无论你找到与否,现在让我们看看上面的更改过后的结果:

    1. sh$ cut-c 93-,-24,36-59 BALANCE-V2.txt
    2. ACCDOC ACCDOCDATE ACCOUNTLIB DEBIT CREDIT
    3. 41012017 TIDE SCHEDULE 00000001615,00
    4. 41012017 VAT BS/ENC 00000000323,00
    5. 41012017 PAYABLES 00000001938,00
    6. 51012017 ACCOMODATION GUIDE 00000001333,00
    7. 51012017 VAT BS/ENC 00000000266,60
    8. 51012017 PAYABLES 00000001599,60
    9. 61012017 PAYABLES 00000001837,20
    10. 61012017 VAT BS/ENC 00000000306,20
    11. 61012017 TOURIST GUIDE BOOK 00000001531,00
    12. 191012017 SEMINAR FEES 00000000080,00
    13. 191012017 PAYABLES 00000000080,00
    14. 281012017 MAINTENANCE 00000000746,58
    15. 281012017 VAT BS/ENC 00000000149,32
    16. 281012017 PAYABLES 00000000895,90
    17. 311012017 PAYABLES 00000000240,00
    18. 311012017 VAT BS/DEBIT 00000000040,00
    19. 311012017 ADVERTISEMENTS 00000000200,00
    20. 321012017 WATER 00000000202,20
    21. 321012017 VAT BS/DEBIT 00000000020,22
    22. 321012017 WATER 00000000170,24
    23. 321012017 VAT BS/DEBIT 00000000009,37
    24. 321012017 PAYABLES 00000000402,03
    25. 341012017 RENTAL COSTS 00000000018,00
    26. 341012017 PAYABLES 00000000018,00
    27. 351012017 MISCELLANEOUS CHARGES 00000000015,00
    28. 351012017 VAT BS/DEBIT 00000000003,00
    29. 351012017 PAYABLES 00000000018,00
    30. 361012017 LANDLINE TELEPHONE 00000000069,14
    31. 361012017 VAT BS/ENC 00000000013,83

    毫无删减地复制了上面命令的输出。所以可以很明显地看出列对齐那里有些问题。

    对此我的解释是原来的数据文件只包含 US-ASCII 编码的字符(符号、标点符号、数字和没有发音符号的拉丁字母)。

    但假如你仔细地查看经软件升级后产生的文件,你可以看到新导出的数据文件保留了带发音符号的字母。例如现在合理地记录了名为 “ALNÉENRE” 的公司,而不是先前的 “ALNEENRE”(没有发音符号)。

    file -i 正确地识别出了改变,因为它报告道现在这个文件是 UTF-8 编码 的。

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

    如果想看看 UTF-8 文件中那些带发音符号的字母是如何编码的,我们可以使用 [hexdump][12],它可以让我们直接以字节形式查看文件:

    1. #为了减少输出,让我们只关注文件的第2
    2. sh$ sed'2!d' BALANCE-V2.txt
    3. 41012017623477 TIDE SCHEDULE ALNÉENRE-4701-LOC 00000001615,00
    4. sh$ sed'2!d' BALANCE-V2.txt |hexdump-C
    5. 0000000034202020202020202020313031323031|4101201|
    6. 0000001037202020202020203632333437372020|7623477|
    7. 0000002020202054494445205343484544554c45| TIDE SCHEDULE|
    8. 000000302020202020202020202020414c4e c3 89| ALN..|
    9. 00000040454e52452d343730312d4c4f43202020|ENRE-4701-LOC |
    10. 0000005020202020202020202020202020303030|000|
    11. 0000006030303030313631352c30302020202020|00001615,00|
    12. 0000007020202020202020202020200a|.|
    13. 0000007c

    在 hexdump  输出的 00000030 那行,在一系列的空格(字节 20)之后,你可以看到:

    • 字母 A 被编码为 41
    • 字母 L 被编码为 4c
    • 字母 N 被编码为 4e

    但对于大写的带有注音的拉丁大写字母 E (这是它在 Unicode 标准中字母 É 的官方名称),则是使用 2 个字节 c3 89 来编码的。

    这样便出现问题了:对于使用固定宽度编码的文件, 使用字节位置来表示范围的 cut 命令工作良好,但这并不适用于使用变长编码的 UTF-8 或者 Shift JIS 编码。这种情况在下面的 POSIX 标准的非规范性摘录 中被明确地解释过:

    先前版本的 cut 程序将字节和字符视作等同的环境下运作(正如在某些实现下对退格键 <backspace> 和制表键 <tab> 的处理)。在针对多字节字符的情况下,特别增加了 -b 选项。

    嘿,等一下!我并没有在上面“有错误”的例子中使用 '-b' 选项,而是 -c 选项呀!所以,难道不应该能够成功处理了吗!?

    是的,确实应该:但是很不幸,即便我们现在已身处 2018 年,GNU Coreutils 的版本为 8.30 了,cut 程序的 GNU 版本实现仍然不能很好地处理多字节字符。引用 GNU 文档 的话说,-c 选项“现在和 -b 选项是相同的,但对于国际化的情形将有所不同[...]”。需要提及的是,这个问题距今已有 10 年之久了!

    另一方面,OpenBSD 的实现版本和 POSIX 相吻合,这将归功于当前的本地化(locale)设定来合理地处理多字节字符:

    1. #确保随后的命令知晓我们现在处理的是 UTF-8编码的文本文件
    2. openbsd-6.3$ export LC_CTYPE=en_US.UTF-8
    3. #使用`-c`选项,`cut`能够合理地处理多字节字符
    4. openbsd-6.3$ cut-c -24,36-59,93- BALANCE-V2.txt
    5. ACCDOC ACCDOCDATE ACCOUNTLIB DEBIT CREDIT
    6. 41012017 TIDE SCHEDULE 00000001615,00
    7. 41012017 VAT BS/ENC 00000000323,00
    8. 41012017 PAYABLES 00000001938,00
    9. 51012017 ACCOMODATION GUIDE 00000001333,00
    10. 51012017 VAT BS/ENC 00000000266,60
    11. 51012017 PAYABLES 00000001599,60
    12. 61012017 PAYABLES 00000001837,20
    13. 61012017 VAT BS/ENC 00000000306,20
    14. 61012017 TOURIST GUIDE BOOK 00000001531,00
    15. 191012017 SEMINAR FEES 00000000080,00
    16. 191012017 PAYABLES 00000000080,00
    17. 281012017 MAINTENANCE 00000000746,58
    18. 281012017 VAT BS/ENC 00000000149,32
    19. 281012017 PAYABLES 00000000895,90
    20. 311012017 PAYABLES 00000000240,00
    21. 311012017 VAT BS/DEBIT 00000000040,00
    22. 311012017 ADVERTISEMENTS 00000000200,00
    23. 321012017 WATER 00000000202,20
    24. 321012017 VAT BS/DEBIT 00000000020,22
    25. 321012017 WATER 00000000170,24
    26. 321012017 VAT BS/DEBIT 00000000009,37
    27. 321012017 PAYABLES 00000000402,03
    28. 341012017 RENTAL COSTS 00000000018,00
    29. 341012017 PAYABLES 00000000018,00
    30. 351012017 MISCELLANEOUS CHARGES 00000000015,00
    31. 351012017 VAT BS/DEBIT 00000000003,00
    32. 351012017 PAYABLES 00000000018,00
    33. 361012017 LANDLINE TELEPHONE 00000000069,14
    34. 361012017 VAT BS/ENC 00000000013,83

    正如期望的那样,当使用 -b 选项而不是 -c 选项后, OpenBSD 版本的 cut 实现和传统的 cut 表现是类似的:

    1. openbsd-6.3$ cut-b -24,36-59,93- BALANCE-V2.txt
    2. ACCDOC ACCDOCDATE ACCOUNTLIB DEBIT CREDIT
    3. 41012017 TIDE SCHEDULE 00000001615,00
    4. 41012017 VAT BS/ENC 00000000323,00
    5. 41012017 PAYABLES 00000001938,00
    6. 51012017 ACCOMODATION GUIDE 00000001333,00
    7. 51012017 VAT BS/ENC 00000000266,60
    8. 51012017 PAYABLES 00000001599,60
    9. 61012017 PAYABLES 00000001837,20
    10. 61012017 VAT BS/ENC 00000000306,20
    11. 61012017 TOURIST GUIDE BOOK 00000001531,00
    12. 191012017 SEMINAR FEES 00000000080,00
    13. 191012017 PAYABLES 00000000080,00
    14. 281012017 MAINTENANCE 00000000746,58
    15. 281012017 VAT BS/ENC 00000000149,32
    16. 281012017 PAYABLES 00000000895,90
    17. 311012017 PAYABLES 00000000240,00
    18. 311012017 VAT BS/DEBIT 00000000040,00
    19. 311012017 ADVERTISEMENTS 00000000200,00
    20. 321012017 WATER 00000000202,20
    21. 321012017 VAT BS/DEBIT 00000000020,22
    22. 321012017 WATER 00000000170,24
    23. 321012017 VAT BS/DEBIT 00000000009,37
    24. 321012017 PAYABLES 00000000402,03
    25. 341012017 RENTAL COSTS 00000000018,00
    26. 341012017 PAYABLES 00000000018,00
    27. 351012017 MISCELLANEOUS CHARGES 00000000015,00
    28. 351012017 VAT BS/DEBIT 00000000003,00
    29. 351012017 PAYABLES 00000000018,00
    30. 361012017 LANDLINE TELEPHONE 00000000069,14
    31. 361012017 VAT BS/ENC 00000000013,83

     

    3、 作用在域上

    从某种意义上说,使用 cut 来处理用特定分隔符隔开的文本文件要更加容易一些,因为只需要确定好每行中域之间的分隔符,然后复制域的内容到输出就可以了,而不需要烦恼任何与编码相关的问题。

    下面是一个用分隔符隔开的示例文本文件:

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

    你可能知道上面文件是一个 CSV 格式的文件(它以逗号来分隔),即便有时候域分隔符不是逗号。例如分号(;)也常被用来作为分隔符,并且对于那些总使用逗号作为 十进制分隔符的国家(例如法国,所以上面我的示例文件中选用了他们国家的字符),当导出数据为 “CSV” 格式时,默认将使用分号来分隔数据。另一种常见的情况是使用 tab 键 来作为分隔符,从而生成叫做 tab 分隔的值 的文件。最后,在 Unix 和 Linux 领域,冒号 (:) 是另一种你能找到的常见分隔符号,例如在标准的 /etc/passwd/etc/group 这两个文件里。

    当处理使用分隔符隔开的文本文件格式时,你可以向带有 -f 选项的 cut 命令提供需要保留的域的范围,并且你也可以使用 -d 选项来指定分隔符(当没有使用 -d 选项时,默认以 tab 字符来作为分隔符):

    1. sh$ cut-f 5--d';' BALANCE.csv |head
    2. ACCDOCLIB;DEBIT;CREDIT
    3. ALNEENRE-4701-LOC;00000001615,00;
    4. ALNEENRE-4701-LOC;00000000323,00;
    5. ALNEENRE-4701-LOC;;00000001938,00
    6. ALNEENRE-4771-LOC;00000001333,00;
    7. ALNEENRE-4771-LOC;00000000266,60;
    8. ALNEENRE-4771-LOC;;00000001599,60
    9. FACT FA00006253 - BIT QUIROBEN;;00000001837,20
    10. FACT FA00006253 - BIT QUIROBEN;00000000306,20;
    11. FACT FA00006253 - BIT QUIROBEN;00000001531,00;

     

    处理不包含分隔符的行

    但要是输入文件中的某些行没有分隔符又该怎么办呢?很容易地认为可以将这样的行视为只包含第一个域。但 cut 程序并 不是 这样做的。

    默认情况下,当使用 -f 选项时,cut 将总是原样输出不包含分隔符的那一行(可能假设它是非数据行,就像表头或注释等):

    1. sh$ (echo"# 2018-03 BALANCE";cat BALANCE.csv)> BALANCE-WITH-HEADER.csv
    2. sh$ cut-f 6,7-d';' BALANCE-WITH-HEADER.csv |head-5
    3. #2018-03 BALANCE
    4. DEBIT;CREDIT
    5. 00000001615,00;
    6. 00000000323,00;
    7. ;00000001938,00

    使用 -s 选项,你可以做出相反的行为,这样 cut 将总是忽略这些行:

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

    假如你好奇心强,你还可以探索这种特性,来作为一种相对隐晦的方式去保留那些只包含给定字符的行:

    1. #保留含有一个`e`的行
    2. sh$ printf"%s\n"{mighty,bold,great}-{condor,monkey,bear}|cut-s -f 1--d'e'

     

    改变输出的分隔符

    作为一种扩展, GNU 版本实现的 cut 允许通过使用 --output-delimiter 选项来为结果指定一个不同的域分隔符:

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

    需要注意的是,在上面这个例子中,所有出现域分隔符的地方都被替换掉了,而不仅仅是那些在命令行中指定的作为域范围边界的分隔符。

     

    4、 非 POSIX GNU 扩展

    说到非 POSIX GNU 扩展,它们中的某些特别有用。特别需要提及的是下面的扩展也同样对字节、字符或者域范围工作良好(相对于当前的 GNU 实现来说)。

    --complement

    想想在 sed 地址中的感叹符号(!),使用它,cut 将只保存没有被匹配到的范围:

    1. #只保留第5个域
    2. sh$ cut-f 5-d';' BALANCE.csv |head-3
    3. ACCDOCLIB
    4. ALNEENRE-4701-LOC
    5. ALNEENRE-4701-LOC
    6. #保留除了第5个域之外的内容
    7. sh$ cut--complement -f 5-d';' BALANCE.csv |head-3
    8. ACCDOC;ACCDOCDATE;ACCOUNTNUM;ACCOUNTLIB;DEBIT;CREDIT
    9. 4;1012017;623477;TIDE SCHEDULE;00000001615,00;
    10. 4;1012017;445452;VAT BS/ENC;00000000323,00;

    --zero-terminated (-z)

    使用 NUL 字符 来作为行终止符,而不是 新行newline字符。当你的数据包含 新行字符时, -z 选项就特别有用了,例如当处理文件名的时候(因为在文件名中新行字符是可以使用的,而 NUL 则不可以)。

    为了展示 -z 选项,让我们先做一点实验。首先,我们将创建一个文件名中包含换行符的文件:

    1. bash$ touch $'EMPTY\nFILE\nWITH FUNKY\nNAME'.txt
    2. bash$ ls-1*.txt
    3. BALANCE.txt
    4. BALANCE-V2.txt
    5. EMPTY?FILE?WITH FUNKY?NAME.txt

    现在假设我想展示每个 *.txt 文件的前 5 个字符。一个想当然的解决方法将会失败:

    1. sh$ ls-1*.txt |cut-c 1-5
    2. BALAN
    3. BALAN
    4. EMPTY
    5. FILE
    6. WITH
    7. NAME.

    你可以已经知道 ls 是为了方便人类使用而特别设计的,并且在一个命令管道中使用它是一个反模式(确实是这样的)。所以让我们用 find 来替换它:

    1. sh$ find.-name '*.txt'-printf"%f\n"|cut-c 1-5
    2. BALAN
    3. EMPTY
    4. FILE
    5. WITH
    6. NAME.
    7. BALAN

    上面的命令基本上产生了与先前类似的结果(尽管以不同的次序,因为 ls 会隐式地对文件名做排序,而 find 则不会)。

    在上面的两个例子中,都有一个相同的问题,cut 命令不能区分 新行 字符是数据域的一部分(即文件名),还是作为最后标记的 新行 记号。但使用 NUL 字节(\0)来作为行终止符就将排除掉这种混淆的情况,使得我们最后可以得到期望的结果:

    1. #我被告知在某些旧版的`tr`程序中需要使用`\000`而不是`\0`来代表 NUL 字符(假如你需要这种改变请让我知晓!)
    2. sh$ find.-name '*.txt'-printf"%f\0"|cut-z -c 1-5|tr'\0''\n'
    3. BALAN
    4. EMPTY
    5. BALAN

    通过上面最后的例子,我们就达到了本文的最后部分了,所以我将让你自己试试 -printf 后面那个有趣的 "%f\0" 参数或者理解为什么我在管道的最后使用了 tr 命令。

     

    使用 cut 命令可以实现更多功能

    我只是列举了 cut 命令的最常见且在我眼中最基础的使用方式。你甚至可以将它以更加实用的方式加以运用,这取决于你的逻辑和想象。

    不要再犹豫了,请使用下面的评论框贴出你的发现。最后一如既往的,假如你喜欢这篇文章,请不要忘记将它分享到你最喜爱网站和社交媒体中!


    via: https://linuxhandbook.com/cut-command/

    作者:Sylvain Leroux 译者:FSSlc 校对:wxy

    本文由 LCTT 原创编译,Linux中国 荣誉推出

    Linux公社的RSS地址:http://www.arianalance.com/rssFeed.aspx

    本文永久更新链接地址http://www.arianalance.com/Linux/2018-08/153520.htm

    linux
    相关资讯       cut命令  Linux cut 命令 
    本文评论   查看全部评论 (0)
    表情: 表情 姓名: 字数

           

    评论声明
    • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
    • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
    • 本站管理人员有权保留或删除其管辖留言中的任意内容
    • 本站有权在网站内转载或引用您的评论
    • 参与本评论即表明您已经阅读并接受上述条款