Linux下如何提取嵌套括号「()」间的文本?求解决方案
在Linux环境下提取嵌套括号间文本的方法
没问题!处理带嵌套括号的文本提取,简单的正则匹配可搞不定,得靠括号计数来精准定位。下面给你两种在Linux终端就能用的实用方法:
方法1:使用awk脚本(推荐,易理解易调整)
awk很适合处理这种需要计数的文本场景,我们可以通过跟踪括号的嵌套层级来提取内容:
awk -v cnt=0 '{ for (i=1; i<=length($0); i++) { char = substr($0, i, 1) if (char == "(") cnt++ # 当处于最外层括号内部时输出字符(排除最外层的左右括号) if (cnt > 1) printf "%s", char if (char == ")") cnt-- } }' your_sql_file.sql
逻辑说明:
- 初始化计数器
cnt为0,遍历文本的每个字符 - 遇到左括号
(就把计数器加1,遇到右括号)就减1 - 只有当计数器大于1时(也就是处于最外层括号的内部),才输出当前字符,这样就自动跳过了最外层的
(和),同时保留内部的嵌套括号(比如CHAR(1)里的括号)
如果是直接处理字符串而不是文件,用管道即可:
echo "CREATE SET TABLE xxxxx.xxxxxx ,NO FALLBACK , NO BEFORE JOURNAL, NO AFTER JOURNAL, CHECKSUM = DEFAULT, DEFAULT MERGEBLOCKRATIO ( aflt_type_cd CHAR(1) CHARACTER SET LATIN UPPERCASE NOT CASESPECIFIC TITLE 'AFFILIATE TYPE CODE', aflt_co_cd CHAR(1) CHARACTER SET LATIN NOT CASESPECIFIC TITLE 'AFFILIATE COMPANY CODE', cris_ind CHAR(1) CHARACTER SET LATIN NOT CASESPECIFIC TITLE 'CUSTOMER RECORDS INFORMATION SYSTEM INDICATOR', cabs_ind CHAR(1) CHARACTER SET LATIN NOT CASESPECIFIC TITLE 'CARRIER ACCESS BILLING SYSTEM INDICATOR', src_feed_cd CHAR(1) CHARACTER SET LATIN NOT CASESPECIFIC TITLE 'SOURCE FEED CODE', intgt_ind CHAR(1) CHARACTER SET LATIN NOT CASESPECIFIC TITLE 'INTEGRATED INDICATOR' NOT NULL, lst_updt_by CHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC TITLE 'LAST UPDATED BY' NOT NULL, load_dt_tm TIMESTAMP(6) TITLE 'LOAD DATE TIME' NOT NULL, updt_dt_tm TIMESTAMP(6) TITLE 'UPDATE DATE TIME' NOT NULL) PRIMARY INDEX nupi_bill_sys ( bill_sys_geo_id );" | awk -v cnt=0 '{for (i=1; i<=length($0); i++) {char = substr($0, i, 1); if (char == "(") cnt++; if (cnt > 1) printf "%s", char; if (char == ")") cnt--}}'
方法2:使用Perl递归正则
Perl支持递归正则表达式,能直接匹配嵌套结构,代码更简洁:
perl -0777 -ne ' while (/(\((?:[^()]|(?R))*\))/g) { $match = $1; print substr($match, 1, -1), "\n"; last; # 只取第一个最外层括号的内容 }' your_sql_file.sql
逻辑说明:
-0777参数让Perl读取整个文件内容(避免换行分割)- 正则里的
(?R)表示递归匹配整个正则模式,完美处理嵌套括号 - 用
substr($match, 1, -1)去掉匹配结果首尾的括号,直接输出内部内容
运行上面的任意一种方法,都能得到你想要的目标文本。
内容的提问来源于stack exchange,提问作者Sahil Hans
相关产品推荐
相关产品推荐

