ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

grammars-v4 中 awk 示例脚本实战指南:用 AWK 对 CSV 文件进行字段检查、统计与清洗

grammars-v4 中 awk 示例脚本实战指南:用 AWK 对 CSV 文件进行字段检查、统计与清洗 grammars-v4 中 awk 示例脚本实战指南用 AWK 对 CSV 文件进行字段检查、统计与清洗【免费下载链接】grammars-v4Grammars written for ANTLR v4; expectation that the grammars are free of actions.项目地址: https://gitcode.com/gh_mirrors/gr/grammars-v4导读本文围绕 grammars-v4 仓库 awk/examples/awk_scripts 目录下的 AWK 脚本集合展开这是一套由 Uwe Geerckendatamelt.com维护的、面向 CSV 类分隔文本文件的数据质量检查与清洗工具。读完本文你将掌握 14 个即拿即用的 AWK 脚本的调用方式与参数约定理解字段定位—统计聚合—查询过滤—清洗转换的完整 CSV 处理链路并能根据脚本头部注释与源码结构快速定制自己的 AWK 数据处理流程。这些.awk文件同时还是仓库内 awk 语法awkLexer.g4、awkParser.g4的合法输入样例因此也适合作为 ANTLR 语法验证与解析测试的数据来源。脚本集合定位与使用前提该目录是 grammars-v4 仓库中 awk 语法的示例资源之一。脚本集合的定位非常明确——README 开篇即说明这是一组对例如 CSV 文件执行特定检查的 AWK 脚本允许自由使用、修改与再发布所有脚本都在开头附有使用说明注释。在使用这套脚本前需要了解两个关键前提字段分隔符默认是分号;尽管 README 与注释中通篇使用CSV一词绝大多数脚本在BEGIN块中设置FS;例如 field_query.awk、field_highlow.awk。也就是说它们面向的是分号分隔的表格数据与常见逗号分隔 CSV 不同直接套用逗号文件时需自行调整FS。默认跳过表头行除 header_fields.awk、number_of_fields_min_max.awk 等少数全量统计脚本外多数脚本默认把第一行当作表头跳过从第二行开始处理若文件没有表头需传入-v noheader1。脚本均以#!/usr/bin/awk -f或#!/usr/bin/gawk -f如 field_permutations.awk、csv2redis.awk开头既可直接执行也可用awk -f 脚本名.awk 参数 输入文件的方式调用。贯穿全部脚本的通用参数约定虽然每个脚本的参数不同但整套脚本遵循高度一致的命名约定理解这些约定后即可触类旁通参数-v 传入含义默认行为fieldnumber指定要处理的字段/列序号从 1 开始多数脚本默认第 1 列若为 0 或超出行的字段数自动回退到第 1 列fieldname指定字段名配合表头行使用脚本从表头行按名称忽略大小写反查列号noheader1声明输入文件无表头行默认认为有表头并从第 2 行开始处理quiet1仅输出核心结果不输出统计摘要默认同时输出评估字段、行数等摘要信息ignorecase1忽略字段内容大小写如Hello与hello归并默认区分大小写nonumbers1不显示计数仅输出排列/匹配值本身默认输出计数以 field_permutations.awk 的注释为例标准调用方式有两种# 按列号指定字段 awk -f field_permutations.awk -v fieldnumber1 -v noheader1 /home/test/datafile.csv # 按表头字段名指定字段且只输出排列值本身 awk -f field_permutations.awk -v fieldnamelastname -v quiet1 /home/test/datafile.csv值得注意的实现细节是当同时提供fieldnumber与表头行时脚本会优先用fieldname在表头中查找列号而列号回退逻辑fieldnumber0 || fieldnumber NF时取第 1 列写在与NR 1绑定的块中即只对首行生效一次。字段定位与文件结构概览这类脚本用于回答我的表有哪些列、某列在第几列、各行列数是否一致等结构性问题是后续所有按列处理工作的前置步骤。header_fields.awk输出表头字段与列位置header_fields.awk 是最简单的脚本之一仅对NR1一行生效用printf %24s %4i将表头字段名右对齐到 24 字符宽、列号右对齐到 4 位输出awk -f header_fields.awk /home/test/datafile.csv输出形如id 1 lastname 2 country 3field_header_position.awk按名称反查列号field_header_position.awk 与上者互补——给定字段名反查其所在列号。必须通过-v fieldname...传入字段名匹配时对表头内容做tolower()忽略大小写源码 L32awk -f field_header_position.awk -v fieldnamecountry /home/testuser/testfile.csv若未找到输出column in header row: [not found]。在脚本头部注释给出的示例中脚本自述文件名为field_query_header.awk与实际文件名略有出入可视为历史遗留的注释误差。number_of_fields_min_max.awk检查各行列数一致性number_of_fields_min_max.awk 遍历所有记录统计每行的字段数NF的最大值与最小值。这在数据质量检查中非常实用若最大值与最小值不一致说明文件中存在行间列数不齐的问题如字段内混入了分隔符反之则可以确认文件结构规整。其输出包括记录总数、字段数高值与低值调用无需任何参数awk -f number_of_fields_min_max.awk /home/testuser/testfile.csv统计与聚合求和、极值、长度分布field_sum.awk对指定列求和field_sum.awk 对指定列做数值累加字符串值会被忽略源码仅执行sum sum $fieldnumber空值直接跳过。fieldnumber为必传参数若文件无表头需加noheader1。脚本在BEGIN阶段把fieldname初始化为fieldnumber随后在首行用NR 1 !noheader条件块替换为真实列名这是少数在条件中显式排除表头的脚本awk -f field_sum.awk -v fieldnumber7 -v noheader1 /home/testuser/testfile.csvfield_highlow.awk输出指定列的最高/最低值field_highlow.awk 输出指定列的高值与低值。注释明确说明可以使用数字或字符串字符串将按字母顺序排序。实现上使用highestValuenull与lowestValuenull作为首次赋值哨兵并对空值字段直接跳过若传入ignorecase1比较前会先tolower字段内容awk -f field_highlow.awk -v fieldnumber7 -v noheader1 /home/testuser/testfile.csv输出包含high value、low value以及处理的总行数不含表头。field_minmax_length.awk输出指定列值的最短/最长长度field_minmax_length.awk 统计指定列中值的最短与最长长度。脚本内置了一个trim()函数用sub(/^ */)与sub(/ *$/)去除首尾空格统计的是去除首尾空格后的length()输出时同时给出对应的最短/最长样本值awk -f field_minmax_length.awk -v fieldnumber7 -v noheader1 /home/testuser/testfile.csv输出形如minimum length: 2 : DE maximum length: 28 : United Kingdom of Great Britain该脚本与 fields_trim.awk 中的trim()函数实现完全一致可以推断这是该脚本作者在多个工具间复用的惯用函数片段。排列与去重字段值的唯一性分析field_permutations.awk单列值排列统计field_permutations.awk 是这套脚本中功能最完整的代表之一用于统计某一列出现了哪些不同的值排列及各自出现次数。它同时支持fieldnumber与fieldname两种指定方式、noheader、quiet、ignorecase、nonumbers全套参数。核心实现是 AWK 的关联数组计数dimension[trim($fieldnumber)]空值统一记为[empty]。默认输出排列明细、排列总数、处理行数以及排列数占总行数的百分比awk -f field_permutations.awk -v fieldnumber1 -v noheader1 /home/test/datafile.csv脚本中还保留了一段被注释掉的asorti()排序代码并在注释中说明数组也可以排序但也可在 shell 中用 sort 命令完成——即输出的排列顺序不保证有序需要排序时可用管道交给sort处理。注意该脚本 shebang 为gawk部分实现依赖 GNU awk 特性。2field_permutations.awk双列组合排列统计2field_permutations.awk 是单列版本的扩展统计两列值组合的排列情况例如国家 × 城市的组合分布。必传参数为fieldnumber1与fieldnumber2两列各自在越界时回退到第 1 列同样支持noheader、quiet、ignorecase、nonumbers。实现上以$fieldnumber1 :: $fieldnumber2作为关联数组键awk -f 2field_permutations.awk -v fieldnumber11 -v fieldnumber23 -v noheader1 /home/test/datafile.csv输出会先打印两列各自的字段名与列号如evaluated fields: country(1) :: city(3)再逐项输出组合与计数最后给出排列总数与占比。查询与过滤按条件抽取数据行field_query.awk按正则匹配指定列筛选行field_query.awk 根据指定列与查询字符串筛选数据行其匹配基于 AWK 正则表达式规则源码条件$fieldnumber ~ query。fieldnumber必传query为匹配模式命中行通过print $0整行输出。quiet1时仅输出命中行否则附加评估字段、查询值、命中行数与总行数的摘要awk -f field_query.awk -v fieldnumber7 -v queryGermany -v noheader1 /home/testuser/testfile.csv由于使用~正则匹配query支持诸如^Ger、[Gg]ermany等正则表达式比精确字符串匹配灵活得多但也意味着query中的正则元字符需要按正则规则转义这一点与纯字符串匹配工具不同。find_non_matching.awk对照匹配文件找出未匹配/匹配值find_non_matching.awk 实现白名单/黑名单式校验读取一个匹配文件每行一个词条#开头或空行被忽略然后在输入文件的指定列中查找等价值最终输出未匹配的值及出现次数传入-v reverse1可反转逻辑改为输出匹配的值。参数包括fieldnumber指定列缺省第 1 列matchingfile匹配文件路径必传未指定时脚本打印错误并exit 1noheader1输入文件无表头nonumbers1不显示出现次数reverse1反转匹配逻辑。./find_non_matching.awk -v fieldnumber4 -v matchingfilematch.txt inputfile.csv ./find_non_matching.awk -v reverse1 -v fieldnumber4 -v matchingfilematch.txt inputfile.csv实现上脚本在BEGIN阶段用getline将匹配文件读入关联数组键统一tolower化因此匹配不区分大小写主循环用entry[tolower($fieldnumber)]查表符合校验数据是否符合预定义取值集合的数据质量场景。结尾摘要会给出匹配文件词条数、输入总行数、找到的元素数以及匹配/未匹配行数。清洗与转换修正字段内容fields_trim.awk去除每个字段的首尾空格fields_trim.awk 对输入每一行的所有字段执行首尾空格裁剪并整行输出。BEGIN中同时设置FSOFS;保证输出仍为分号分隔。内部trim()通过两次sub()正则替换完成去开头空格^ *与结尾空格*$。由于脚本没有表头跳过逻辑它会原样处理所有行包括表头适合对整表做统一清洗awk -f fields_trim.awk inputfile.csv outputfile.csvcapitalize_all_words.awk单词首字母大写capitalize_all_words.awk 将文本中的单词首字母大写、其余字符小写。其capitalizeWords()函数以空格切分文本对每个词执行toupper(substr(word,1,1)) tolower(substr(word,2))后重组。脚本头部注释未列出参数但源码中引用了一个exceptions变量按逗号切分可推断设计意图是支持例外字段不转换需要提醒的是源码中存在一行print xxx: result;调试输出且例外判断逻辑resultexc[i]后if(result)才转换与注释意图并不完全吻合可视为该脚本的已知瑕疵——使用者应结合自身数据验证输出或按需修改后再用于生产。replace_invalid_values.awk用默认值替换空值/null 值replace_invalid_values.awk 将不可用/不希望保留的空值统一替换为默认值产出不含任何空值或 null 值的结果文件。脚本在BEGIN中定义DEFAULT_VALUE[undefined]对每一行的每个字段检查以下任一条件即替换字符串null、NULL、Null大小写变体空字符串或单个空格 AWK 的null值以~开头的值正则$f ~ /^~/推测用于标记缺失/待定类占位符。awk -f replace_invalid_values.awk inputfile.csv outputfile.csv替换逻辑写在普通主循环中不区分表头与数据行若希望表头也参与替换检查如表头恰好是null这一设计反而有利。replace_matches.awk按键值映射表替换指定列replace_matches.awk 实现字典式替换先加载一个属性文件风格的替换表每行键值如EUREurope再将输入文件指定列中匹配键的值替换为对应的值。参数fieldnumber要检查并替换的列号substitutionfile替换表文件路径devider键值分隔符默认为可覆盖。脚本头部注释给出了完整的端到端示例替换表subst.txt含EUREurope、USAUnited States of America、MEAMiddle East输入文件第 4 列含EUR、USA、AFR等值时AFR无映射保持不变EUR变为Europe./replace_matches.awk -v fieldnumber4 -v substitutionfilesubst.txt inputfile.csv实现要点BEGIN阶段用index()定位分隔符、substr()拆分键值并装入关联数组以#开头的行视为注释忽略主循环查表命中则改写$fieldnumber未命中则原样输出。脚本注释特别提醒两个陷阱一是替换值中不要包含分隔符;否则会产生行列数不一致的输出二是替换表中的分隔符不应出现在数据本身否则键值拆分会出错。进阶csv2redis.awk——CSV 直灌 RedisREADME.md 正文列出的 14 个脚本之外目录中还存在一个未在清单中登记、但同样完整的 csv2redis.awk2019-08-04 更新作者邮箱为 uwe.geerckenweb.de。它把 CSV 数据转换为 Redis 协议格式供redis-cli --pipe批量导入为 Redis Hash前提输入 CSV必须有表头行表头列名将作为 Redis Hash 的字段名separator列分隔符默认逗号,注意这与其余脚本默认分号不同rediskeyRedis 键前缀默认csvfile实际键为rediskey:记录IDuidcolumn用作记录唯一 ID 的列号从 1 开始缺省使用行号字符集问题文件含é、à、ö、ä等特殊字符时建议给 awk 加-b标志。awk -f csv2redis.awk csv_filename.csv awk -v separator\t -f csv2redis.awk csv_filename.csv awk -v uidcolumn2 -v rediskeymyfile -f csv2redis.awk csv_filename.csv awk -b -f csv2redis.awk csv_filename.csv | redis-cli --pipe其核心是toRedisProtocol()函数按 RESPREdis Serialization Protocol手工拼装HMSET命令*开头的参数个数行、$开头的长度前缀行以及键、列名、列值序列。例如某行数据会被编码为*N\r\n$5\r\nHMSET\r\n...形式的命令流。由于输出直接就是协议字节流配合redis-cli --pipe可避免逐条往返的网络开销。与 awk 语法仓库的关联示例即测试输入这套脚本不仅是独立可用的工具集还是仓库 awk 语法定义的有效输入样例。从 awk/desc.xml 的配置可以看到targetsAntlr4ng;Cpp;CSharp;Dart;Go;Java;OphiRust;Python3;TypeScript/targets inputsexamples/**/*.awk/inputs即examples/**/*.awk通配模式会匹配到awk_scripts/下的全部.awk文件以及examples/根目录的 average_score.awk、count_words.awk、domain_name.awk 等它们被用作该 ANTLR4 awk 语法的解析测试输入目标覆盖 Antlr4ng、Cpp、CSharp、Dart、Go、Java、OphiRust、Python3、TypeScript 等运行时。换言之这些脚本本身是被 awkLexer.g4 与 awkParser.g4 实际解析过的合法 awk 程序——这也是脚本可以放心直接运行之外的又一层保障。若你想验证某个改写后的脚本仍是合法 awk 语法可通过仓库的构建/测试流程将其纳入语法解析验证。使用注意事项与限制总结最后汇总这套脚本在实战中的注意事项均以源码注释与实现为据分隔符不统一绝大多数脚本默认FS;唯独 csv2redis.awk 默认逗号,且可通过separator覆盖。混用前务必确认输入文件的真实分隔符。表头语义需显式声明默认跳过第一行无表头文件请传noheader1而 fields_trim.awk、replace_invalid_values.awk、number_of_fields_min_max.awk 等不区分表头会处理所有行。空值与大小写处理各有差异排列类脚本将空值归一为[empty]查询/校验类脚本对空值直接跳过替换类脚本对null/NULL/Null/空串/空格/~开头值统一替换ignorecase1仅部分脚本支持。排序不保证排列输出基于 AWK 关联数组遍历顺序不定需要排序时用管道交给sort。已知瑕疵capitalize_all_words.awk 含有调试输出行且例外逻辑与注释不完全一致field_header_position.awk 注释中的示例文件名与实际不符。使用前建议先在小样本上验证输出。依赖差异field_permutations.awk 与 csv2redis.awk 的 shebang 是gawk若你的环境只有 mawk/BSD awk部分写法可能需要适配。总体而言这套脚本把 CSV 类数据最常见的检查与清洗需求——结构摸底、字段定位、求和与极值、唯一值分布、正则筛选、白名单校验、空格裁剪、空值替换、字典映射、甚至直灌 Redis——都封装成了可独立运行的 AWK 单文件工具。它们既是随手可用的数据处理工具也是学习如何用 AWK 关联数组 BEGIN/NR/NF/END 惯用法组织数据处理程序的极佳参考实现。【免费下载链接】grammars-v4Grammars written for ANTLR v4; expectation that the grammars are free of actions.项目地址: https://gitcode.com/gh_mirrors/gr/grammars-v4创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表