2014-01-06 78 views
2

我有這樣的行的文件:bash的正則表達式查找線,重複的單詞

"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(背參考)相匹配。但是,輸出是零。 我該怎麼做?

+0

嗯,你的正則表達式工作正常,我在我的正則表達式測試器。所以這似乎是與事情的背後的一面。也許嘗試簡化以取出數組,然後僅測試一個字符串。 – acarlon

+1

但是在Bash中這樣做似乎不自然。 'sed -n s/def {\([^}] * \)} * def {\ 1}/\ 1/p'文件' – tripleee

回答

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 
$ 

這似乎只在擊V4工作,但是。

+0

您測試了這個嗎? Bash正則表達式不支持反向引用,這是行不通的。 –

+0

@BenjaminW。是的 - 我測試了它 - 在bash 4.x版本(例如Ubuntu 14.04)上,反引用*做*工作。然而,它不適用於bash 3.2.x(例如OS X) - 請參閱tripleee的編輯。簡化測試命令:'re =「([a-z])[0-9] \ 1」; [A1A =〜$重新] &&回聲$ {BASH_REMATCH [0]}' –

+0

太奇怪了,它不爲我擊42年3月4日(MSYS2)的工作,即使'男子3 regex'提到反向引用.. 。 –

0

在bash的循環是很慢,這可能是對於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中,你有什麼事情,是更容易擴展和維護。

0

是的,很多方法可以做到這一點,包括:

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

使用sed的

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

"def{word} def{word}" 

如果只導出詞

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

word