在awk内外使用变量:将awk变量传递给Shell的实现方案
问题
我用awk编写脚本,用于检测.cls文件中不在try/catch块内的System.debug语句,脚本能正常完成检测,但想要在检测到这类违规语句时让脚本返回失败状态(exit 1),遇到了两个问题:
- 直接在匹配块中添加
exit 1会立刻终止awk进程,无法继续检测后续的违规语句 - 尝试用计数变量
i统计违规次数,但awk内部的变量无法直接传递到外部shell环境
原awk检测脚本:
BEGIN { IGNORECASE = 1 } /try\s*{/ { in_try_block=1 } /catch\s*\(/ { in_catch_block=1 } /}/ { if (in_catch_block) { in_catch_block=0 } else if (in_try_block) { in_try_block=0 } } /System\.debug/ && !in_try_block && !in_catch_block { print "\033[1;31mError: System.debug found in " FILENAME ": Line " NR ": " $0 "\033[0m" }
尝试过但变量无法传递的修改:
awk ' BEGIN { IGNORECASE = 1 } /try\s*{/ { in_try_block=1 } /catch\s*\(/ { in_catch_block=1 } /}/ { if (in_catch_block) { in_catch_block=0 } else if (in_try_block) { in_try_block=0 } } /System\.debug/ && !in_try_block && !in_catch_block { print "\033[1;31mError: System.debug found in " FILENAME ": Line " NR ": " $0 "\033[0m" i++ } ' "$file" if [[ i -gt 0 ]]; then exit 1 fi
示例待检测类代码:
@isTest public class GenerateDocumentTest { public static final String AUTH_PATH = 'Auth Path'; public static final String SAMPLE_DATA = '{"key": "value"}'; @TestSetup static void setupTestData() { try { // Insert test site insert new Site__c(Active__c = true, Site_Code__c = 'TestCode'); // Insert test contact insert new Contact(FirstName = 'John', LastName = 'Doe', Email = 'test@example.com'); // Insert test account insert new Account(Name = 'Test Account', Phone = '123456789', Email = 'account@example.com'); // Insert test product and pricebook entry Product2 testProduct = new Product2(Name = 'Sample Product', IsActive = true); insert testProduct; insert new PricebookEntry( Product2Id = testProduct.Id, Pricebook2Id = Test.getStandardPricebookId(), UnitPrice = 100, IsActive = true ); } catch (Exception ex) { System.debug('Setup error: ' + ex.getMessage()); } } @isTest static void testDocumentGeneration() { try { System.debug('Testing document generation...'); // Add test logic here } catch (Exception ex) { System.assert(false, 'Test failed: ' + ex.getMessage()); } } }
最简解决方案
方法1:通过awk END块输出计数,shell捕获后判断
让awk在处理完文件后,在END块中输出违规次数,shell通过命令替换捕获该数值,再判断是否返回失败状态。为避免错误信息干扰计数捕获,将错误信息输出到标准错误流:
# 捕获awk输出的违规次数 error_count=$(awk ' BEGIN { IGNORECASE = 1 error_count = 0 } /try\s*{/ { in_try_block=1 } /catch\s*\(/ { in_catch_block=1 } /}/ { if (in_catch_block) { in_catch_block=0 } else if (in_try_block) { in_try_block=0 } } /System\.debug/ && !in_try_block && !in_catch_block { # 错误信息输出到stderr,不干扰计数捕获 print "\033[1;31mError: System.debug found in " FILENAME ": Line " NR ": " $0 "\033[0m" > "/dev/stderr" error_count++ } # 最后输出计数到stdout,供shell捕获 END { print error_count } ' "$file") # 根据计数判断是否返回失败状态 if [[ "$error_count" -gt 0 ]]; then exit 1 fi
方法2:直接通过awk的退出状态判断
如果只需要知道是否存在违规(不需要具体次数),可以让awk在END块中根据计数设置退出状态,shell直接判断awk的返回值:
awk ' BEGIN { IGNORECASE = 1 error_count = 0 } /try\s*{/ { in_try_block=1 } /catch\s*\(/ { in_catch_block=1 } /}/ { if (in_catch_block) { in_catch_block=0 } else if (in_try_block) { in_try_block=0 } } /System\.debug/ && !in_try_block && !in_catch_block { print "\033[1;31mError: System.debug found in " FILENAME ": Line " NR ": " $0 "\033[0m" error_count++ } # 有违规则返回非0状态 END { exit (error_count > 0 ? 1 : 0) } ' "$file" # 判断awk的退出状态,非0则触发失败 if [[ $? -ne 0 ]]; then exit 1 fi
内容的提问来源于stack exchange,提问作者Kenruth
相关产品推荐
相关产品推荐

