跳转到内容

Unix/命令/文本处理指南

来自维基教科书,开放世界中的开放书籍

Unix 支持多种文本处理命令。

awk 是一个强大的文本处理工具,使用正则表达式,提供了超出 #cut#sed 的扩展功能。您可以在 AWKAWK 入门 维基教科书中了解更多信息。

单行示例

  • echo abcd |awk '/b.*d/'
    • 输出与正则表达式匹配的行,类似于 grep 命令。
  • echo abcd |awk '/b.*d/ {print $0}'
    • 与上面相同,使用显式 print 语句。$0 代表整行。
  • echo ab   cd |awk '/b.*d/ {print $2}'
    • 对于与正则表达式匹配的行,输出第二个字段。默认情况下,使用空格序列作为字段分隔符。因此,输出“cd”。
  • echo abcd,e |awk -F, '/b.*d/ {print $2}'
    • 对于与正则表达式匹配的行,输出第二个字段,由于 -F 选项,使用逗号作为字段分隔符。因此,输出“e”。
  • echo abcd,e |awk '{print toupper($0)}'
    • 输出所有行的大写字母。对于小写字母,使用“tolower”。
  • echo a b c d | awk '{print $NF, $(NF-1)}'
    • 输出最后一个字段和倒数第二个字段;NF 是字段数。
  • echo ab cd | awk 'NF>=2'
    • 输出字段数为 2 或更多的行。
  • echo ab cd | awk '{print NF}'
    • 对于每一行,输出其中的字段数。
  • echo ab cd | awk 'length($2) > 1'
    • 输出所有第二字段长度大于 1 的行。
  • echo ab cd | awk '$2 ~ /cd/'
    • 输出第二字段与正则表达式匹配的所有行。
  • echo ab cd | awk '$1 ~ /ab/ && $2 ~ /cd/'
    • 与上面类似,但使用由“&&”连接的两个子条件。支持 C 编程语言中已知的其他逻辑运算符。
  • cat file.txt | awk 'NR >= 100 && NR <= 500'
    • 输出行号在指定范围内的行(记录)。因此,充当行号过滤器。
  • cat file.txt | awk 'NR == 1 || /reg.*pattern/'
    • 输出第一行和与正则表达式匹配的行。
  • echo abcd | awk '{gsub(/ab/,"ef");print}'
    • 替换也称为替换,类似于 sed 命令;gsub 中的“g”代表全局。
  • awk 'BEGIN{for(i=1;i<6;i++) print sqrt(i)}'
    • 输出 1、...、5 中整数的平方根。BEGIN{} 的使用确保即使没有输入行馈送到 awk,代码也会执行。for 循环使用熟悉的 C 语言语法,sqrt 是可用的多个数学函数之一。
  • awk 'BEGIN{printf "%i %.2f\n", 1, (2+3)/7}'
    • 支持来自 C 语言的熟悉函数 printf,作为不需要围绕参数的括号的语句。
  • awk 'BEGIN{for(i=1;i<9;i++) a[i]=i^2; for(i in a) print i, a[i]}'
    • 在 awk 关联数组也称为映射或字典的帮助下,输出一对整数及其平方。输出的顺序是不确定的,这在关联数组中是常见的。awk 没有其他编程语言中已知的数组和列表的直接模拟。
  • cat file.txt | awk '{sum+=$1} END{print sum}'
    • 使用 END 关键字输出第一个字段(列)中值的总和。
  • awk 'BEGIN{system("dir")}'
    • 运行外部命令 dir;在沙箱模式下禁用。
  • awk 'function abs(x) {return x < 0 ? -x : x} BEGIN{print abs(-4)}'
    • 定义和使用绝对值函数。显示了 C 语言中已知的三元运算符的使用。

链接

输出两个文件中共同的或独有的行,前提是文件已排序。如果文件未排序,则输出是不确定的。选项控制识别方式,例如仅输出共同的行。

示例

  • seq 1 5 > file1; seq 3 7 > file2
    • 将整数序列 1...5 和 3...7 输出到文件以支持以下 comm 使用示例。
  • comm file1 file2
    • 如果文件已排序,则输出三列,第一列是 file1 中独有的行,第二列是 file2 中独有的行,第三列是两个文件中共同的行。列默认以制表符分隔,但制表符仅用于前导缩进,并且输出的每一行都只有一列填充。
  • comm -23 file1 file2
    • 如果文件已排序,则输出 file1 中不在 file2 中的行。因此,对行执行集合差运算。开关表示要从输出中省略的列。
  • comm -12 file1 file2
    • 如果文件已排序,则输出两个文件中都存在的行。因此,对行执行集合交运算。
  • printf "1\n1\n" > file1; printf "1\n" > file2; comm file1 file2
    • 第一行被评为两个文件中都存在的,而 file1 的第二行被评为 file1 中独有的。因此,不仅考虑行内容,而且将重复行视为要匹配的独立项来处理。
  • seq 1 5 > file1; seq 3 7 | comm file1 -
    • 使用连字符 (-) 表示标准输入。

链接

将输入拆分为输出文件。拆分可以由行数和正则表达式匹配驱动。

链接

输出文本文件中各行中的选定列(“字段”),并指定列分隔符。另请参见 Cut 维基教科书。

示例

  • cut -f1 file.txt
    • 输出每一行的第一个字段,使用制表符作为字段分隔符。
  • echo a:b | cut -d: -f2
    • 输出每一行的第二个字段,使用冒号作为字段分隔符。
  • echo a b c | cut -d" " -f1,3
  • echo a b c d e | cut -d" " -f1-3,5
  • echo a b c | cut -d" " -f3,2,1
    • 输出“a b c”,忽略 -f 之后的反转顺序。
  • echo a b c d | cut -d" " -f2-
    • 输出第二个和所有后续字段,因此为“b c d”。
  • echo abcd | cut -c3,4
    • 不处理字段,而是处理字符。因此,输出“cd”。
  • echo abcdefgh | cut -c1-3,6-8
    • 输出 abcfgh

链接

将制表符转换为空格,默认情况下每个制表符为 8 个空格。另请参见 #unexpand.

链接

格式化文本,包括将段落重新排列为每行特定最大字符数。似乎没有被 POSIX 覆盖

链接

以不同于 #fmt 的方式限制每行最大长度。

链接

  • fold, opengroup.org
  • 4.3 fold 在 GNU Coreutils 手册中,gnu.org

在字符编码之间转换。

示例

  • iconv -f ISO-8859-2 -t UTF-8 < in.txt > out.txt
    • 从 (-f) ISO-8859-2 转换为 (-t) UTF-8。

链接

根据字段将来自多个文件的行合并在一起,假设这些文件是根据用于合并的字段排序的。

链接

添加行号。

链接

  • nl, opengroup.org
  • 3.3 nl 在 GNU Coreutils 手册中,gnu.org

对于多个文件,将对应于行号的行连接起来,就好像每个文件是表格的一列,每个文件行是表格的一行一样。

链接

格式化输入以供打印,包括带有页眉和页脚的分页。

链接

sed,一个流编辑器,以其文本替换功能而闻名,支持正则表达式,但可以做更多。您可以在 Sed Wikibook 中了解更多信息。

替换的单行示例

  • sed "s/concieve/conceive/" myfile.txt
    • 替换每行中 "concieve" 的第一次出现。
  • sed "s/concieve/conceive/g" myfile.txt
    • 替换所有出现,因为末尾有 "g"。
  • sed "s/concieve/conceive/g;s/recieve/receive/g" myfile.txt
    • 执行两次替换。
  • echo "abccbd" | sed "s/a\([bc]*\)d/\1/g"
    • 输出 "bccb"。使用 \( 和 \) 来标记一个组,并使用 \1 来引用替换部分中的组。
    • 可能只适用于 GNU sed;待验证。
  • echo "abccbd" | sed -r "s/a([bc]*)d/\1/g"
    • 在 GNU sed 中,它与前面的示例做同样的事情,只是使用 -r 来启用扩展正则表达式,从而避免了在 "(" 前面放置反斜杠来表示分组的必要性。
    • -r 开关在 GNU sed 中可用,而在原始的 Unix sed 中不可用。
  • echo "a  b" | sed -r "s/a\s*b/ab/g"
    • 在 GNU sed 中,输出 "ab"。使用 "\s" 来表示空格,并使用 "*" 来使前面的字符组迭代任意次数。需要 -r 来在 GNU sed 中启用扩展正则表达式。
  • sed "s/\x22/'/g" myfile.txt
    • 在 GNU sed 中,将每个引号替换为一个单引号。\x22 指的是十六进制 ASCII 值为 22 的字符,即引号。
  • echo Hallo | sed "s/hallo/hello/gi"
    • 忽略字符大小写,因为末尾有 "i"。不保留大小写,输出 "hello" 而不是 "Hello"。
  • echo a2 | sed "s/[[:alpha:]]/z/g"
    • 输出 z2,使用 "[[:alpha:]]",它代表任何字母。注意,字符类在手册中列为 "[:alpha:]",带有单个 "["。

链接

对文件中的行进行排序,输出排序后的行,并将输入保持不变。

示例

  • sort file.txt
    • 按字母顺序对文件进行排序。
  • sort file.txt file2.txt
    • 按字母顺序对两个文件的行进行排序,输出来自两个文件的一个排序后的行流。
  • cat file.txt | sort
    • 对 cat 创建的输入流进行排序。因此,等效于 sort file.txt。
  • sort -n file.txt
    • 对文件进行数字排序。因此,12 放在 2 之后,而字母顺序则不是这样。
  • sort -r file.txt
    • 按相反顺序对文件进行排序。因此,b 放在 a 之前。
  • sort -k5,5 file.txt
    • 通过 -k 对文件按第 5 个字段(列)进行排序。
  • sort -t, -k5,5 file.txt
    • 如上所述,通过 -t 使用逗号 (,) 作为字段分隔符。
  • sort -k5,5 -k3,3 file.txt
    • 首先按第 5 个字段对文件进行排序,然后按第 3 个字段进行排序。
  • sort -k5,5 -k3,3n file.txt
    • 如上所述,但当按第 3 个字段排序时,通过附加的 "n" 按数字顺序进行排序。
  • sort -k5 file.txt
    • 首先按第 5 个字段对文件进行排序,然后对所有剩余字段进行排序,忽略排序目的的第 1-4 个字段。
  • sort -u file.txt
    • 对文件进行排序,删除重复的行,从而确保每行输出都是唯一的。
  • sort -u -k5,5 file.txt
    • 按第 5 个字段对文件进行排序,仅保留具有相同键的每组行中的一个行,其中键是第 5 个字段。

链接

执行拼写检查。似乎在 POSIX 中不存在。

链接

执行字符映射或“转换”,以及更多操作。对于某些任务,它比 sed 更简洁。

示例

  • echo "a:b:c:d" | tr : \\n
    • 通过冒号 (:) 分割成多行。冒号不会出现在输出中。
  • echo "a b c d" | tr " " \\n
    • 通过空格分割成多行。
  • echo "abba" | tr ab cd
    • 将 a 替换为 c,将 b 替换为 d。因此,产生 cddc。
  • echo "a,b:c,d:e" | tr ,: :,
    • 交换逗号和冒号。因此,产生 a:b,c:d,e。
  • echo "a b c d" | tr -d " "
    • 从输入中删除空格,输出 abcd。-d 代表删除。
  • echo "a,b,c:d:e" | tr -dc ,
    • 仅保留逗号和冒号。-c 代表补集。因此,产生 ,,::.
  • echo "a,,,b,c::d" | tr -s ,
    • 将逗号序列替换为一个逗号,将冒号序列替换为一个冒号。-s 代表压缩。因此,产生 a,b,c:d。

链接

将空格转换为制表符,默认情况下每个制表符占 8 个空格。

链接

从每个相同行块中输出单行,等等。理想情况下与排序后的输入一起使用。您可以在 Uniq 维基教科书中了解更多信息。

示例

  • uniq file.txt
    • 对于相邻的一个或多个相同的行,只输出其中一行。
  • sort file.txt | uniq
    • 对相同行进行排序,然后只输出其中一行。排序确保最初不相邻但相同的行变得相邻。
  • sort file.txt | uniq -u
    • 只输出单行块。
  • sort file.txt | uniq -d
    • 输出每块的多行块中的单行,过滤掉单行。
  • sort file.txt | uniq -c
    • 在每行之前加上块大小。
  • sort file.txt | uniq -c | sort
    • 在每行之前加上块大小,并按块大小对结果进行排序。由于 uniq 输出的大小通过空格缩进,因此排序效果很好,即使是按字母顺序排列。
  • sort file.txt | uniq -u -d
    • 在 GNU uniq 中,不输出任何内容,因为每个选项都充当过滤器,组合在一起后它们会过滤掉所有内容。

链接

华夏公益教科书