如何从queueN.txt中提取每行首尾括号内的字符串?
提取文本中每行首尾括号内的内容
问题描述
现有queueN.txt文件,内容如下:
uid=524357(aali95) gid=524357(aali95) groups=524357(aali95),611684(com_perkinsd),695433(bios420) uid=524534(aalman4) gid=524534(aalman4) groups=524534(aalman4),426634(chem_shared) uid=748146(abaner29) gid=748146(abaner29) groups=748146(abaner29) uid=583567(abench2) gid=583567(abench2) groups=583567(abench2),875029(cs494_paka) uid=570875(abhima4) gid=570875(abhima4) groups=570875(abhima4),875029(cs494_paka) uid=603522(abokifa) gid=603522(abokifa) groups=603522(abokifa),750403(cme_abokifa),831682(vasphpc) uid=747491(aboyap2) gid=747491(aboyap2) groups=747491(aboyap2),10(wheel),516955(acr_admin) uid=500092(adavar2) gid=500092(adavar2) groups=500092(adavar2),10513(domain_users),426636(cme_shared),605853(cme_sarakad),831682(vasphpc) uid=543988(adench2) gid=543988(adench2) groups=543988(adench2),545740(phys_hyowon) uid=738525(aditya06) gid=738525(aditya06) groups=738525(aditya06),705095(acr_workshop)\
需要提取每行中第一组括号内的字符串和最后一组括号内的字符串,输出格式如下:
aali95 bios420 aalman4 chem_shared abaner29 abaner29 abench2 cs494_paka abhima4 cs494_paka abokifa vasphpc aboyap2 acr_admin adavar2 vasphpc adench2 phys_hyowon aditya06 acr_workshop
你尝试的脚本存在逻辑错误:for f in \cat queueN.txt`; do cat ${f} | sed 's...'; done > queue.txt 会把文件内容按空格拆分成单个单词赋值给f,而非逐行处理,且cat ${f}`会尝试读取以单词命名的文件,完全不符合需求。
解决方案
方法1:使用sed一行完成
利用sed的正则匹配,直接捕获并替换目标内容,兼容单行单括号的情况:
sed -E 's/.*\(([^)]+)\)(.*\(([^)]+)\))?$/\1 \3/' queueN.txt | sed 's/ $//' > queue.txt
- 解释:
.*\(([^)]+)\):匹配任意字符直到第一个(,捕获括号内的非)字符(第一个目标内容)(.*\(([^)]+)\))?$:匹配剩余内容直到最后一个(,捕获括号内的内容(最后一个目标内容),?$表示这部分可选(兼容单行单括号的情况)- 第二个
sed 's/ $//':处理单行单括号的行,去掉末尾多余的空格
方法2:使用awk处理(更直观)
awk逐行提取所有括号内的内容,再输出首尾两项:
awk '{ count = 0 while (match($0, /\(([^)]+)\)/, arr)) { content[++count] = arr[1] $0 = substr($0, RSTART + RLENGTH) } print content[1], content[count] }' queueN.txt > queue.txt
- 解释:
- 用
match函数循环匹配每行中的括号内容,存入数组content - 最后输出数组的第一个元素和最后一个元素
- 用
方法3:改进循环(符合你最初的思路)
如果一定要用循环逐行处理,用while read替代for避免拆分单词:
while IFS= read -r line; do first=$(echo "$line" | sed -E 's/.*\(([^)]+)\).*/\1/') last=$(echo "$line" | sed -E 's/.*\(([^)]+)\)$/\1/') echo "$first $last" done < queueN.txt > queue.txt
while IFS= read -r line:逐行读取文件内容,保留空格和特殊字符- 分别用sed提取第一个和最后一个括号内的内容,再拼接输出
内容的提问来源于stack exchange,提问作者anikaM
相关产品推荐
相关产品推荐

