我怎样才能转换这个:
foo (blah) (bar 80)
foo (cats) (blat 92)
对此:
foo bar 80
foo blat 92
我想保留所有不在括号中的文本。
我只想提取括号内包含字符串“bar”或“blat”的文本。
不包含“blat”或“bar”的括号对应该被忽略。
最好使用 Sed 或 awk
答案1
使用sed
:
< inputfile sed 's/(\([^\)]*\(bar\|blat\)[^\)]*\))/\1/g; s/(.*) //g'
输入文件:
test (bar) (blat)
bar (testblat) (bartest)
blat (testbar) (barblat) (no) (blatanother)
输出文件:
test bar blat
bar testblat bartest
blat testbar barblat blatanother
分解:
#1:
(
: 匹配一个(
字符\(
:开始对捕获组进行分组[^\)]*
: 匹配 0 个或多个字符,不)
\(
:开始对允许的字符串进行分组bar
:匹配第一个允许的字符串\|
: 分隔第二个允许的字符串blat
:匹配第二个允许的字符串\)
:停止对允许的字符串进行分组[^\)]*
: 匹配 0 个或多个字符,不)
\)
:停止对捕获组进行分组)
: 匹配一个)
字符
#2:
(
: 匹配一个(
字符.*
: 匹配 0 个或多个字符)
: 匹配一个)
字符: 匹配一个
字符
答案2
虽然这在sed
或中确实是可能的awk
,但使用 Perl 要容易得多(至少对我来说):
$ perl -ple '@pars=( /(\(.+?\))/g );
for $par (@pars){
s/\s*.$par.// unless $par=~/blat|bar/
} s/[()]//g;' file
foo bar 80
foo blat 92
解释
-ple
:在输入文件上执行脚本p
后,打印输入文件的每一行。删除尾随换行符,并在每次调用时添加换行符。e
-l
print
@pars=( /(\(.+?\))/g );
:@pars
数组现在包含括号内的所有字符串。for $par (@pars){ ... }
:针对上面找到的每个字符串。s/\s*.$par.// unless $par=~/blat|bar/
:如果这组括号不包含blat
或,则删除它们bar
。s/[()]//g;
:删除所有括号(而不是括号内的文本)。
您还可以高尔夫球将以上内容浓缩为
perl -ple 'for$par((/(\(.+?\))/g)){$par=~/blat|bar/||s/\s*.$par.//};s/[()]//g;' file
答案3
使用python
:
#!/usr/bin/env python2
import re
with open('/path/to/file.txt') as f:
for line in f:
pat_list = re.findall(r'\(([^)]*?)\)', line.rstrip())
for pat in pat_list:
if not re.search(r'(?:blat|bar)', pat):
print re.sub(r'\(|\)', '', line.replace(' ({0})'.format(pat), '').rstrip())
输出:
foo bar 80
foo blat 92
- 这里我们使用了的
re
(正则表达式)模块python
。 pat_list
将包含括号内的字符串列表pat_list
然后我们在成员中搜索“blat”或“bar”的存在- 如果没有找到,我们将打印该行并删除不必要的部分,包括括号。
答案4
有点晚了,但是,单线简单的力量怎么样:
> cat test.py
from string import replace
stuff = '''
foo (blah) (bar 80)
foo (cats) (blat 92)
'''
for i in stuff.split('\n'): # split by \n
if i != str(): # not empty string
print ''.join(i.split()[0]+' '+i.split()[2]+' '+i.split()[3]).replace('(','').replace(')','')
>>> python test.py
foo bar 80
foo blat 92