bash正则表达式查找具有重复单词的行

时间:2014-01-06 23:42:45

标签: regex bash backreference

我有一个包含这样的行的文件:

"def{word}  def{word}"
"def{worad} def{worads}"

我想报告两次出现的支撑词。 因此,在这种情况下,输出应该只是“单词” 我所拥有的是:

#!/bin/bash
arr=(
   "def{word}  def{word}"
   "def{worad} def{worads}"
)
for i in "${arr[@]}"; do 
   [[ $i =~ def\{([a-z]+)\}.*def\{\1\} ]] || continue
   echo ${BASH_REMATCH[1]}
done

即,我尝试将第一个单词与\ 1(后向引用)匹配。但是,输出为零。 我怎么能这样做?

4 个答案:

答案 0 :(得分:2)

我发现bash正则表达式在用引号括起来时表现得更好,即使你必须要小心这一点,因为直接引用会导致完全而不是正则表达式匹配。要解决此问题,您可以将正则表达式放在引号中,然后在=~表达式中引用它:

#!/bin/bash
arr=(
   "def{word}  def{word}"
   "def{worad} def{worads}"
)
re="def\{([a-z]+)\}.*def\{\1\}"
for i in "${arr[@]}"; do 
   [[ $i =~ $re ]] || continue
   echo ${BASH_REMATCH[1]}
done

输出:

$ ./worad.sh 
word
$ 

但这似乎只适用于Bash v4。

答案 1 :(得分:1)

使用sed

sed -n '/\({[^{]*}\).*\1/p' file

"def{word}  def{word}"

如果只导出单词

sed  -n 's/.*{\([^{]*\)}.*{\1}.*/\1/p' file

word

答案 2 :(得分:0)

bash中的for循环非常慢,对于bash来说这可能有点复杂。我建议使用python或awk。这是python中的一些代码,可以做你想做的事情:

#!/usr/bin/env python

import re
import sys 
import itertools

def freq(alist):
    counts = {}
    for x in alist:
        x = x[1:-1]
        counts[x] = counts.get(x,0) + 1 
    return {m:[j[0] for j in n] for m,n in itertools.groupby(counts.iteritems(), lambda y: y[1])}

for line in sys.stdin:
    counts = freq(re.findall(r'\{[^}]*\}', line))
    if 2 in counts:
        print ' '.join(counts[2])
    else:
        print

假设此脚本位于名为two.py的文件中,则运行如下:

cat yourfile | python two.py

现在它已经在python中,你可以更容易地扩展和维护。

答案 3 :(得分:0)

是的,有很多方法可以做到这一点,包括:

perl -lne '/def\{(.+?)\}.*def\{\1\}/ and print $1' filename