CSH脚本中基于关键词提取正则捕获组的问题求助
在CSH脚本中根据关键词提取缩进文本的解决方案
原代码的问题分析
- 转义字符未解析:csh中直接将
"\n\t"赋值给变量时,这些是字面量字符串,不会被转换为实际的换行和制表符,导致正则无法匹配预期的层级结构。 - expr正则限制:
expr使用POSIX基本正则表达式(BRE),不支持*?这类非贪婪量词,也不识别\s(需用[[:space:]]替代),同时BRE缺乏正向预查等高级特性,难以实现需求。
基于grep的解决方案
你提到的grep -Po是可行方案,以下是具体实现:
1. 修正变量赋值(处理转义字符)
如果是硬编码的字符串,需要用echo -e解析转义字符,让变量存储实际的换行和制表符:
#!/bin/csh -f # 用echo -e解析转义字符,得到实际的换行/制表符 set source = "`echo -e 'Smurfs\n\tPapa\nStar Trek\n\tRenegades\n\tStar Wars\n\tThe Empire Strikes Back\n'`" set toFind = "Star Trek"
2. 编写grep正则表达式
使用grep -Po提取目标内容,正则各部分含义:
(?<=$toFind\n):正向后顾断言,匹配$toFind字符串加换行符之后的位置(确保只匹配关键词所在行的下一行)\t:匹配缩进的制表符\K:重置匹配输出起点,后续内容才会被打印(避免输出制表符).*:匹配制表符后的所有文本(即你需要的结果)
完整命令:
set match = `grep -Po "(?<=$toFind\n)\t\K.*" <<< "$source"` echo $match
运行后,当toFind="Star Trek"时输出Renegades,toFind="Star Wars"时输出The Empire Strikes Back,符合预期。
3. 从文件读取文本的情况
如果实际是从文件读取(而非变量),直接将文件路径作为grep的参数即可,无需处理变量转义:
set toFind = "Star Trek" set match = `grep -Po "(?<=$toFind\n)\t\K.*" your_input_file.txt` echo $match
补充说明
- 正则适配:如果你的缩进是空格而非制表符,只需将正则中的
\t替换为对应的空格(比如代表4个空格),或用[[:space:]]+匹配任意数量空白符。 - csh变量注意事项:变量替换时要加双引号,避免空格导致的字符串拆分问题(比如
"$source"和"$toFind"必须用引号包裹)。
内容的提问来源于stack exchange,提问作者Sarah Weinberger
相关产品推荐
相关产品推荐

