Skip to content
← 返回文件与文本处理列表
文件与文本处理任务与配置

命令与脚本:文本处理与检索 · 提取字段、排序去重与比较合并 ​

返回分篇目录

提取字段、排序去重与比较合并 ​

先提取字段,再排序和统计。uniq 只折叠相邻重复行;join 的两个输入须按连接字段排序,paste 则逐行拼接。

cut · 从标准输入或文件中剪切字段 ​

更多信息:https://www.gnu.org/software/coreutils/manual/html_node/cut-invocation.html。

  • 打印每行的特定字符/或属性范围:
bash
{{命令}} | cut --{{characters|fields}} {{1|1,10|1-10|1-|-10}}
  • 打印每行由指定分隔符分割的属性范围:
bash
{{命令}} | cut {{[-d|--delimiter]}} "{{分隔符}}" {{[-f|--fields]}} {{1|1,10|1-10|1-|-10}}
  • 打印文件每行的字符范围:
bash
cut {{[-c|--characters]}} {{1|1,10|1-10|1-|-10}} {{路径/到/文件}}
  • 打印以 NUL 结尾的行的特定字段(例如 find . -print0)而不是换行符:
bash
{{命令}} | cut {{[-z|--zero-terminated]}} {{[-f|--fields]}} {{1}}

awk · 一种用于文件处理的通用编程语言 ​

另请参阅:gawk。 更多信息:https://github.com/onetrueawk/awk。

  • 以空格为分隔符,打印文件每行第五列(也称作字段):
bash
awk '{print $5}' {{文件名}}
  • 以空格为分隔符,打印文件包含“foo” 的所有行的第二列:
bash
awk '/{{foo}}/ {print $2}' {{文件名}}
  • 以逗号而不是空格作为分隔符,打印文件每行的最后一列:
bash
awk -F ',' '{print $NF}' {{文件名}}
  • 计算文件的第一列数值之和并打印:
bash
awk '{s+=$1} END {print s}' {{文件名}}
  • 从第一行开始,每三行打印一行:
bash
awk 'NR%3==1' {{文件名}}
  • 根据条件不同,打印不同内容:
bash
awk '{if ($1 == "foo") print "Exact match foo"; else if ($1 ~ "bar") print "Partial match bar"; else print "Baz"}' {{文件名}}
  • 打印第 10 列等于指定值的所有行:
bash
awk '($10 == 指定值)'
  • 打印第 10 列介于最小值和最大值之间的所有行:
bash
awk '($10 >= 最小值 && $10 <= 最大值)'

sort · 对文本文件的行进行排序 ​

更多信息:https://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html。

  • 以升序对文件进行排序:
bash
sort {{路径/到/文件}}
  • 以降序对文件进行排序:
bash
sort {{[-r|--reverse]}} {{路径/到/文件}}
  • 以不区分大小写的方式对文件进行排序:
bash
sort {{-f|--ignore-case}} {{路径/到/文件}}
  • 用数字而不是字母顺序对文件进行排序:
bash
sort {{[-n|--numeric-sort]}} {{路径/到/文件}}
  • 按每行的第 3 个字段对 /etc/passwd 进行数字排序,使用 “:” 作为字段分隔符:
bash
sort {{[-t|--field-separator]}} {{:}} {{[-k|--key]}} {{3n}} {{/etc/passwd}}
  • 对一个文件进行排序,只保留唯一的行:
bash
sort {{[-u|--unique]}} {{路径/到/文件}}
  • 对一个文件进行排序,将输出结果打印到指定的输出文件中(可以用来对一个文件进行原地排序):
bash
sort {{[-o|--output]}} {{路径/到/文件}} {{路径/到/文件}}
  • 对带有指数的数字进行排序:
bash
sort {{[-g|--general-numeric-sort]}} {{路径/到/文件}}

uniq · 输出输入或文件中的唯一行 ​

因为它只检测相邻的重复行,所以需要先对它们进行排序。 另请参阅:sort。 更多信息:https://www.gnu.org/software/coreutils/manual/html_node/uniq-invocation.html。

  • 仅显示每行一次:
bash
sort {{路径/到/文件}} | uniq
  • 仅显示唯一的行:
bash
sort {{路径/到/文件}} | uniq {{[-u|--unique]}}
  • 仅显示重复的行:
bash
sort {{路径/到/文件}} | uniq {{[-d|--repeated]}}
  • 显示每行的出现次数及其内容:
bash
sort {{路径/到/文件}} | uniq {{[-c|--count]}}
  • 显示每行的出现次数,并按出现次数从高到低排序:
bash
sort {{路径/到/文件}} | uniq {{[-c|--count]}} | sort {{[-nr|--numeric-sort --reverse]}}

wc · 计数行、单词或字节 ​

更多信息:https://www.gnu.org/software/coreutils/manual/html_node/wc-invocation.html。

  • 计数文件中的行数:
bash
wc {{[-l|--lines]}} {{路径/到/文件}}
  • 计数文件中的单词数:
bash
wc {{[-w|--words]}} {{路径/到/文件}}
  • 计数文件中的字节数:
bash
wc {{[-c|--bytes]}} {{路径/到/文件}}
  • 计数文件中的字符数(考虑所有多字节的字符):
bash
wc {{[-m|--chars]}} {{路径/到/文件}}
  • 使用 stdin,按顺序计数行、单词和字节:
bash
{{find .}} | wc
  • 计算最长行的显示宽度(按当前locale和制表位,不等于字符数):
bash
wc {{[-L|--max-line-length]}} {{路径/到/文件}}

paste · 合并文件行 ​

更多信息:https://www.gnu.org/software/coreutils/manual/html_node/paste-invocation.html。

  • 将所有行合并为一行,使用 tab 作为分隔符:
bash
paste {{[-s|--serial]}} {{路径/到/文件}}
  • 使用指定的分隔符将所有行合并为一行:
bash
paste {{[-s|--serial]}} {{[-d|--delimiters]}} {{分隔符}} {{路径/到/文件}}
  • 并排合并两个文件,每个文件以 tab 分隔为单独的列:
bash
paste {{路径/到/文件1}} {{路径/到/文件2}}
  • 并排合并两个文件,每个文件以指定的分隔符分隔为单独的列:
bash
paste {{[-d|--delimiters]}} {{分隔符}} {{路径/到/文件1}} {{路径/到/文件2}}
  • 将两个文件中的所有行,交替合并:
bash
paste {{[-d|--delimiters]}} '\n' {{路径/到/文件1}} {{路径/到/文件2}}

join · 在两个已排序的文件中根据一个公共字段合并行 ​

更多信息:https://www.gnu.org/software/coreutils/manual/html_node/join-invocation.html。

  • 根据第一个(默认)字段合并两个文件:
bash
join {{路径/到/文件1}} {{路径/到/文件2}}
  • 使用逗号(而不是空格)作为字段分隔符合并两个文件:
bash
join -t ',' {{路径/到/文件1}} {{路径/到/文件2}}
  • 将文件1的字段3与文件2的字段1合并:
bash
join -1 {{3}} -2 {{1}} {{路径/到/文件1}} {{路径/到/文件2}}
  • 为文件1中的每行未配对的行生成一行:
bash
join -a {{1}} {{路径/到/文件1}} {{路径/到/文件2}}
  • 从 stdin 合并一个文件:
bash
cat {{路径/到/文件1}} | join - {{路径/到/文件2}}

diff · 比较文件或目录 ​

另请参阅:delta, difft。 更多信息:https://manned.org/diff。

  • 比较文件 (列出从原文件到新文件的修改):
bash
diff {{原文件}} {{新文件}}
  • 比较文件,忽视空白字符:
bash
diff {{[-w|--ignore-all-space]}} {{原文件}} {{新文件}}
  • 比较文件,并排展示文件差异:
bash
diff {{[-y|--side-by-side]}} {{原文件}} {{新文件}}
  • 比较文件,以统一形式展示不同区别 ( 形式同 git diff):
bash
diff {{[-u|--unified]}} {{源文件}} {{新文件}}
  • 递归地比较目录 (展示不同文件和目录的名字和差异):
bash
diff {{[-r|--recursive]}} {{old_directory}} {{new_directory}}
  • 比较目录(只展示不同文件的文件名):
bash
diff {{[-r|--recursive]}} {{[-q|--brief]}} {{old_directory}} {{new_directory}}
  • 根据两个文本文件的差异,为 Git 创建补丁文件,不存在的文件会被视为空文件:
bash
diff {{[-a|--text]}} {{[-u|--unified]}} {{[-N|--new-file]}} {{原文件}} {{新文件}} > {{diff.patch}}
  • 比较文件,打印彩色的输出,并尽可能找出最小的改变:
bash
diff {{[-d|--minimal]}} --color=always {{原文件}} {{新文件}}

unexpand · 将空格转换为制表符 ​

更多信息:https://www.gnu.org/software/coreutils/manual/html_node/unexpand-invocation.html。

  • 将每个文件中的空格转换为制表符,并写入到 stdout:
bash
unexpand {{路径/到/文件}}
  • 将空格转换为制表符,从 stdin 读取:
bash
unexpand
  • 转换所有空格,而不仅仅是开头的空格:
bash
unexpand {{[-a|--all]}} {{路径/到/文件}}
  • 仅转换开头的空格序列(覆盖 -a):
bash
unexpand --first-only {{路径/到/文件}}
  • 将制表符间隔设置为某个字符数,而不是 8(启用 -a):
bash
unexpand {{[-t|--tabs]}} {{数量}} {{路径/到/文件}}

basename · 移除一个路径的目录部分字符 ​

另请参阅:dirname。 更多信息:https://www.gnu.org/software/coreutils/manual/html_node/basename-invocation.html。

  • 仅显示文件名:
bash
basename {{路径/到/文件}}
  • 显示路径字符最右边表示目录的字符:
bash
basename {{路径/到/目录/}}
  • 展示无后缀的文件名称:
bash
basename {{路径/到/文件}} {{后缀}}

printf · 格式化并打印文本 ​

另请参阅:echo。 更多信息:https://www.gnu.org/software/coreutils/manual/html_node/printf-invocation.html。

  • 打印文本消息:
bash
printf "{{%s\n}}" "{{文本}}"
  • 以粗体蓝色打印整数:
bash
printf "{{\e[1;34m%.3d\e[0m\n}}" {{42}}
  • 打印带有 Unicode 欧元符号的浮点数:
bash
printf "{{\u20AC %.2f\n}}" {{123.4}}
  • 打印由环境变量组成的文本消息:
bash
printf "{{var1: %s\tvar2: %s\n}}" "{{$VAR1}}" "{{$VAR2}}"
  • 将格式化消息存储在变量中(不适用于 Zsh):
bash
printf -v {{变量名}} {{"这是 %s = %d年\n" "今" 2016}}
  • 打印十六进制、八进制和科学计数法数字:
bash
printf "{{hex=%x octal=%o scientific=%e}}" 0x{{FF}} 0{{377}} {{100000}}

q · 在 CSV 和 TSV 文件上执行类似 SQL 的查询 ​

更多信息:https://harelba.github.io/q/。

  • 指定分隔符为 ',' 来查询 CSV 文件:
bash
q {{[-d|--delimiter]}} ',' "SELECT * from {{路径/到/文件}}"
  • 查询 TSV 文件:
bash
q {{[-t|--tab-delimited]}} "SELECT * from {{路径/到/文件}}"
  • 查询带有表头行的文件:
bash
q {{[-d|--delimiter]}} {{分隔符}} {{[-H|--skip-header]}} "SELECT * from {{路径/到/文件}}"
  • 从 stdin 读取数据;查询中的 '-' 代表来自 stdin 的数据:
bash
{{输出}} | q "select * from -"
  • 在列 c1 上连接两个文件(在例子中别名为 f1 和 f2):
bash
q "SELECT * FROM {{路径/到/文件1}} f1 JOIN {{路径/到/文件2}} f2 ON (f1.c1 = f2.c1)"
  • 使用包含输出标题行的输出分隔符来格式化输出(注意:命令将根据输入文件标题或在查询中覆盖的列别名输出列名):
bash
q {{[-D|--output-delimiter]}} {{分隔符}} {{[-O|--output-header]}} "SELECT {{列}} as {{别名}} from {{路径/到/文件}}"

继续阅读