如何仅删除Bash脚本中前11个数组定义后的行内注释
需求背景
我在编写Bash脚本时,为开头的元配置语句添加了大量行内注释,这些注释均位于数组定义行的末尾,固定出现在) #模式之后,共计11处;脚本后续代码中也存在同格式的数组行尾注释,这类注释必须完整保留,且不同脚本中这11个数组定义前的前置内容行数不固定。
处理前的脚本片段:
#!/bin/bash # Title and other notes information ## I may have other lines here, or not ruler=( monarch ) # Type of leader kingdom=( "Island" ) # Type of territory zipcode=( 90210 ) # Standard, 3-12 digits, hyphens allowed datatype=( 0-9- ) # Datatype favoritepie=( "Cherry" ) # A happy memory aoptions=( "Home address" "Work address" "Mobile" ) # List custom options boptions=( ) # List secondary options aopttypes=( string string phonenum ) # Corresponding datatypes for options bopttypes=( ) # Corresponding datatypes for secondary options sourced=( ) # Sourced text in this script, such as settings subscripts=( installusr ) # Valid BASH scripts that this script may call ... # Script continues outsidethewire=( "key 971" ) # Leave this comment here somearray=( "sliced apples" "pie dough" ) # Mother's secret recipe
处理后的预期效果:
#!/bin/bash # Title and other notes information ## I may have other lines here, or not ruler=( monarch ) kingdom=( "Island" ) zipcode=( 90210 ) datatype=( 0-9- ) favoritepie=( "Cherry" ) aoptions=( "Home address" "Work address" "Mobile" ) boptions=( ) aopttypes=( string string phonenum ) bopttypes=( ) sourced=( ) subscripts=( installusr ) ... # Script continues outsidethewire=( "key 971" ) # Leave this comment here somearray=( "sliced apples" "pie dough" ) # Mother's secret recipe
需求规则:
- 仅移除每个文件中最先出现的11处数组定义行后的
) #及后续注释内容 - 11处匹配之后出现的所有同格式注释必须完整保留
- 11个数组定义前的内容长度不固定,可能存在其他普通注释行
现有尝试与问题
目前测试过几种实现方案,均存在缺陷:
- 全局sed替换:执行
sed 's/ ) # .*/ )/' *会替换所有匹配项,误删脚本后续需要保留的注释 - 单匹配sed写法:首匹配语法
sed '0,/ ) # .*/s// )/' *仅能处理每个文件的第一处匹配,无法覆盖前11处 - 循环执行sed:循环11次执行上述首匹配sed的脚本会对所有匹配文件统一计数,无法按单文件维度统计匹配次数,逻辑存在缺陷,容错性差。
实现方案
直接用awk实现即可,天然支持单文件独立计数,逻辑清晰容错性高,不需要编写复杂循环。
Linux环境默认自带的GNU awk支持原地修改,直接执行以下命令即可批量处理目标脚本:
awk -i inplace ' # 每个新文件开始时重置匹配计数器 FNR == 1 { count = 0 } # 匹配次数不足11次、且当前行包含) # 模式时执行替换 count < 11 && /\) # / { sub(/\) #.*/, ")") count++ } # 输出所有行(修改/未修改的内容均原样输出) 1' *.sh
逻辑说明:
- 计数器按文件独立重置,不会出现跨文件累计计数的问题,每个文件单独统计前11处匹配
- 仅对前11处匹配的行做注释删除操作,计数器满11后所有行直接原样输出,后续的行尾注释完全不会被改动
- 匹配规则严格锚定
) #模式,不会误改数组内容、普通行注释等非目标内容
注意:操作前建议先预览效果确认无误,去掉-i inplace参数将结果输出到临时文件对比即可:
awk ' FNR == 1 { count = 0 } count < 11 && /\) # / { sub(/\) #.*/, ")") count++ } 1' target_script.sh > preview_result.sh
如果待处理文件不是.sh后缀,把命令末尾的*.sh替换为对应的文件匹配范围即可。
内容的提问来源于stack exchange,提问作者Jesse
相关产品推荐
相关产品推荐

